perm filename BOOT10.MAC[SS,SYS]1 blob sn#729213 filedate 1983-11-11 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00070 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00012 00002	TITLE	BOOT - A NEW VERSION OF THE LEVEL D DISK BOOTSTRAP  BOOVER BOOMIN BOOEDT BOOTVA
C00016 00003		SUBTTL	REVISION HISTORY 
C00019 00004		SUBTTL	CODING CONVENTIONS/CONSIDERATIONS 
C00024 00005		SUBTTL	PARAMETER DEFINITIONS  .CHBEL .CHCNH .CHTAB .CHLFD .CHVTB .CHFFD .CHCRT .CHCNU .CHCNZ .CHESC .CHDEL FL.RUB FL.OVW FL.WLD FL.RIB FL.EXR FL.ZER FL.IO FL.LDE FL.FFL FR.DEV FR.FIL FR.EXT FR.PTH FR.RBT FR.DMP FR.LOD FR.STA FR.1ST FR.ALL FX.CLR
C00029 00006	MONITOR PARAMETERS WHICH MUST AGREE WITH COMMON/COMMOD.  HOMNAM HOMSNM HOMLUN HOMBSC HOMSCU HOMCNP HOMCLP HOMBPC HOMREF HOMMFD HOMCOD CODHOM HOMSLF RIBFIR RIBPPN RIBNAM RIBEXT RIBSIZ RIBSTS RIPDMP RIBXRA RIPNUB RIBCOD CODRIB RIBSLF BOOTSA BOOTWD LBNHOM LB2HOM LBOBAT LIMLVL MBTCOM MAXPGS .EPHSB
C00033 00007	MISCELANEOUS HARDWARE PARAMETERS  IT.DON IT.BSY APRRST CLRAPR PDLLEN LINBFL BLKSIZ PAGSIZ MAXUNI P2BLSH B2WLSH W2BLSH P2WLSH W2PLSH .VBOOT .VPAG0 .VMOVE .VZERO .MBOOT .MPAG0 .MMOVE .MZERO
C00038 00008	IFN FTKL10!FTKI10,<  CI.XDN CI.122 CI.1ER CI.1RA CI.2ER CI.2RA CO.XDN CO.XSX CO.XMI CO.1RB CO.1AE CO.2RB CO.2ME DO.XCR DO.XSR DI.XCE DI.XSM DI.XSB DO.XDS DO.XDT DO.XDC DO.1CR DO.2ST DO.XCL DO.XRP DO.XRD DO.XWT RH2TRA RH2JMP R2IOWL R2BCNT R2WCNT R1BCNT R1WCNT
C00044 00009	IFN FTKS10,<  SO.UPR SO.VFT SO.RBT SO.USR SO.UBI SI.UER SO.CS1 SI.RDY SI.S1E SO.WC SO.BA SO.DA SO.CS2 SO.DS SO.DSM SO.DSB SI.DT SI.DSK SO.DC SO.DCL SO.RIP SO.WRT SO.RED RSBCNT
C00047 00010		SUBTTL	MACRO DEFINITIONS  OFFSET OFFSET LABEL BTSLOC
C00050 00011	MACROS TO HELP IN INSERTING ENTRIES INTO THE PAGE MAP  ZZ ZZ
C00053 00012		SUBTTL	DATA AREAS  .RDATA BTSLOC EPTABS R2IOWD BTSLOC
C00058 00013	BLK(HOM,BLKSIZ)		HOM BLOCK FOR CURRENT UNIT  SWTVLV SWTVLL FILSPE NXMTBE
C00063 00014	HERE AFTER BEING LOADED INTO MEMORY.  WE ARE (PROBABLY) RUNNING  BOOT
C00069 00015	HERE WHEN THE .VBOOT ADDRESS SPACE HAS BEEN MAPPED TO DO SOME ONCE  MAPPED
C00073 00016	ROUTINE TO PROMPT THE USER AND DUMP/LOAD/RELOAD THE MONITOR.  CALL  RLDMON RLDMO1 RLDMO2
C00078 00017	CHGEBR:  CHGEBR CHGUBR VERMSG
C00081 00018		SUBTTL	DUMP MONITOR  ASKSTR DODUMP DODUM1 DODUM2 DODUM3 DODUM4
C00086 00019	HERE IF AN ERROR IS DETECTED IN THE DUMP OR LOAD.  USE THE ERROR  LODERR DMPERR DMPER1 DMPER2 DMPER3
C00091 00020	TABLE OF ERROR MESSAGES INDEXED BY THE ERROR CODE RETURNED IN T1.  EMSTAB FNFOFS EMSTBL DMPDSP DMPDSL LODDSP LODDSL STRFUL
C00096 00021	ROUTINE TO DUMP THE MONITOR ONTO THE CRASH FILE SPECIFIED IN THE  DUMP DUMP1 DUMP2
C00102 00022	DUMP3:	MOVE	T1,[SV.END,,1]	GET END OF DESCRIPTOR MARKER  DUMP3 DUMP4 DUMP5 DUMP6
C00107 00023		SUBTTL	RELOAD MONITOR  DOLOAD DOLOA1 DOLOA2 DOLOA3
C00111 00024	ROUTINE TO LOAD A NEW MONITOR INTO CORE. CALL WITH THE FILESPEC AREA  LOAD LOAD1 LOAD2 LOAD3 LOAD4 LOAD5 LOAD6 LOAD7
C00117 00025		SUBTTL	FILE SEARCH SUBROUTINES  FNDMON
C00121 00026	ROUTINE TO FIND A FILE AND SETUP ITS RIB IN RIB.  CALL WITH  FNDFIL FNDFI1 FNDFI2
C00125 00027	ROUTINE TO FIND THE MFD FOR A STRUCTURE.  CALL WITH DEV CONTAINING  FNDMFD FNDMF1 SRCHFD SRCHF1 SRCHF2
C00130 00028		SUBTTL	BLOCK READ/WRITE SUBROUTINES  WRTRIB WRTBUF REDBUF
C00134 00029	ROUTINE TO POSITION AN EXE FILE SO THAT THE NEXT READ WILL READ  POSFIL REDBLK
C00139 00030	ROUTINE TO FIND A UNIT AND READ IT'S HOM BLOCK. CALL WITH LUNPOS  FNDLUN FNDUNI FNDUN1 FNDUN2 FNDUN3
C00144 00031	ROUTINE TO READ A HOM BLOCK.  REDHOM REDHO1 REDHO2
C00148 00032	ROUTINE TO READ A RIB.  REDRIB REDRBP
C00153 00033	ROUTINE TO SETUP A TRANSFER TO/FROM DISK.  SELBLK SELBL1 SELBL2 SELBL3
C00156 00034	SELBL4:	MOVN	M,T1		GET -VE NUMBER OF BLOCKS IN REQUEST  SELBL4 SELBL5 SELBL6
C00161 00035		SUBTTL	SUPPORT SUBROUTINES  CLRBUF SETIOT ERRTAB SNTERR FNTERR UPDERR EOFERR IOFERR BDFERR MCCERR NSSERR ERRTBL ALLERR
C00165 00036	ROUTINE TO READ DATA INTO A VIRTUAL ADDRESS.  VRTRED VRTWRT MAPADR
C00170 00037	ROUTINE TO SAVE P1 AND P2 AND CALL THE CALLER AS A COROUTINE  SAVE2 SAVFR
C00174 00038		SUBTTL	MOVE BOOT TO TOP OF MEMORY AND ZERO CORE  MOVBTS
C00179 00039	HERE AFTER HAVING MOVED BOOT TO THE TOP OF CORE TO ZERO ALL OTHER  MOVBT1 MOVBT2
C00183 00040		SUBTTL	NXMTAB HANDLING ROUTINES  FINDHI FINDH1 FINDH2 FNDPGS FNDPG1 FNDPG2
C00188 00041	ROUTINE TO CHECK NXMTAB TO SEE IF A PAGE EXISTS.  CHKNXM SUNXMT SUNXM1 SUNXM2
C00193 00042	ROUTINE TO DETERMINE IF A PAGE EXISTS IN MEMORY BY TOUCHING  REFMEM REFTRP
C00197 00043		SUBTTL	TRAP HANDLING  TRAP PFTRAP PFTRA1
C00201 00044	ROUTINE TO PRINT THE CONI APR AND RDERA (IF A KL10).  PRTAPR
C00204 00045		SUBTTL	COMMAND PARSING  PARSE PARSE1 PARSE2 PARSE3 CMDERR TRMTAB TRMTBL
C00208 00046	HERE TO PROCESS DEVICE IN COMMAND STRING  CMDDEV CMDFIL CMDPTH CMDPT1 CMDPT2
C00213 00047	HERE TO PROCESS THE END OF THE COMMAND LINE  CMDEOL
C00216 00048	HERE TO PROCESS A SWITCH IN THE COMMAND STRING  CMDSWT CMDSW1 CMDSW2 SWTTAB SWTTBL
C00220 00049		SUBTTL	COMMAND	INPUT  STOFIL GETSIX GETSI1 GETSI2 GETOCT GETOC1
C00225 00050	ROUTINE TO RETURN THE NEXT CHARACTER FROM THE COMMAND STREAM.  GETCHR ASKYN CPOPJ1 CPOPJ
C00229 00051	ROUTINE TO PRINT A PROMPT STRING, AND READ A COMMAND LINE INTO  REDLIN REDLI1 REDLI2 TPOPJ
C00233 00052	HERE TO PROCESS RUBOUTS  REDRUB REDRU1 REDCNU REDCU1
C00237 00053		SUBTTL	COMMAND OUTPUT  PRRBCR PRCRLF PRBSL PRCOMA PRLBKT PRRBKT PRMSG PRMSG1 PRSIX
C00242 00054	ROUTINE TO PRINT AN OCTAL NUMBER ON THE CTY.  PROCT PRHWD PRHWD1 PRHWD2 ECHO
C00245 00055	ROUTINE TO PRINT THE CURRENT FILESPEC FROM THE DATA BASE.  PRFILE PRFIL1
C00249 00056		SUBTTL	LOWEST LEVEL CTY INPUT/OUTPUT ROUTINES  TYO DODTE
C00253 00057	ROUTINE TO READ ONE CHARACTER FROM THE CTY.  TYI BRKTAB
C00257 00058		SUBTTL	DISK SUPPORT SUBROUTINES  REDREG DRVTYP DRVTY1
C00261 00059	TABLES DEFINING THE DRIVE TYPES OF THE DRIVES WE KNOW ABOUT AND  DRTTAB DRTTBL BPCTAB BPTTAB
C00264 00060		SUBTTL	BYTE POINTERS INTO DATA STRUCTURES  DESRBU DENRBU DESRBA DENRBA DEYRBU DEYRBA
C00267 00061		SUBTTL	TABLES DRIVING DEVICE DEPENDENT I/O  DVCTAB DVCTBL IOTTAB DODATO DODATI DOCONI DOCONO DOCNSO IOTTBL
C00271 00062	THE FOLLOWING TABLES GIVE THE DISPATCH ADDRESSES FOR THE CONTROLLER  OFS REDTAB WRTTAB
C00275 00063	IFN FTKL10!FTKI10,<  R12WRT R12RED R12XFR R10XFR R12XF1
C00280 00064	ROUTINE TO SETUP THE CHANNEL COMMAND LIST FOR THIS TRANSFER AND  R12SET R12SE1 R12SE2 R12SE3 R12SE4 R12SE5 R12SE6
C00286 00065	ROUTINE TO INITIALIZE THE RH10/RH20 FOR A TRANSFER.  R12INI R12CHK
C00290 00066	ROUTINE TO WAIT FOR THE RH10/RH20 TO FINISH A TRANSFER.  R12WAT R12CLR
C00294 00067	IFN FTKS10,<  R11WRT R11RED R11XFR R11XF1
C00299 00068	ROUTINE TO SETUP THE UBA MAPPING REGISTERS, AND THE DRIVE REGISTERS  R11SET R11SE1
C00304 00069	ROUTINE TO INITIALIZE THE RH11 FOR A TRANSFER.  R11INI R11CLR
C00308 00070		$DEPHASE  BOOLEN BOOPGS BOOEND
C00309 ENDMK
C⊗;
TITLE	BOOT - A NEW VERSION OF THE LEVEL D DISK BOOTSTRAP ;⊗ BOOVER BOOMIN BOOEDT BOOTVA
SUBTTL	G.M. UHLER/GMU	05 JUL 80


	SEARCH	F,S
	IFN FTKL10,<
	SEARCH	DTEPRM
	>
	SALL

;COPYRIGHT (C) 1980 BY
;DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.
;
;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.
;
;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.


BOOVER==1		;MAJOR VERSION NUMBER
BOOMIN==0		;MINOR VERSION NUMBER
BOOEDT==4		;EDIT NUMBER



;DEFINE THE SYMBOL FTPAGE TO BE THE FIRST PHYSICAL PAGE INTO WHICH
;BOOT IS TO BE LOADED.  THEN LOC THE ASSEMBLY TO THAT POINT.

IFNDEF FTPAGE,<FTPAGE==773>
	LOC	<FTPAGE*1000>	;START ASSEMBLY AT THAT ADDRESS


BOOTVA:				;FIRST VIRTUAL ADDRESS IN BOOT
	SUBTTL	REVISION HISTORY ;⊗


COMMENT `

1   05-Feb-80	Add the /REBOOT switch and support for system sleep.
2   15-Jun-80	Change the default filename for /REBOOT from SYSTEM to
		CRASH.
3   05-Jul-80	Change the definitions of APRRST and CLRAPR for the
		KS10 to reflect empirical evidence (i.e. make it work)
4   05-Jul-80	After powerup, the KS10 wants a WREBR 0 before the
		WREBR to set the EBR.  I'm not sure why it's true or
		why it works but it fixes the ?PAR ERR's.

`
	SUBTTL	CODING CONVENTIONS/CONSIDERATIONS ;⊗


;AC CONVENTIONS IN THIS PROGRAM:
;
; S	- FLAGS (SEE FL.XXX, FR.XXX)
; J	- INDEX INTO DEVICE CODE TABLE
; U	- PHYSICAL UNIT NUMBER
; W	- OFFSET INTO TYPE TABLE (RH10, RH20, RH11, ETC.)
; R	- PHYSICAL OR VIRTUAL CORE ADDRESS OF START OF TRANSFER
; F	- LOGICAL BLOCK ON UNIT OF FIRST BLOCK TO TRANSFER
; M	- NUMBER OF BLOCKS TO TRANSFER
; T1-T4	- TEMPORARIES.  NOT GUARENTEED ACROSS SUBROUTINE CALLS EXCEPT
;	  WHERE EXPLICITLY NOTED.
; P1,P2	- PRESERVED REGISTERS (ACROSS SUBROUTINE CALLS)
; P3,P4 - FILENAME, EXTENSION OF FILE BEING SEARCHED FOR. MAY
;	  NOT BE PRESERVED ACROSS ALL SUBROUTINE CALLS
;
;
;THIS PROGRAM IS CONSTRUCTED IN TWO PARTS.  THE FIRST STARTS AT THE
;LABEL BOOT WHERE WE START EXECUTION UNPAGED AS WE ARE LOADED INTO
;MEMORY.  THE FIRST THING THAT WE DO IS TURN ON PAGING, MAPPING THE
;LOW 256K OF MEMORY 1 FOR 1.  THE 1 FOR 1 MAP IS ASSEMBLED IN SO THE
;WE DON'T HAVE TO BUILD IT AT RUN TIME.  WE THEN CHANGE THE EPT
;TO MAP PHYSICAL MEMORY INTO THE .VBOOT VIRTUAL ADDRESS SPACE AND
;THEN JUMP INTO IT.
;
;THE SECOND, AND MOST SUBSTANTIAL, PART OF BOOT RUNS IN THE .VBOOT
;VIRTUAL ADDRESS STARTING AT THE VIRTUAL ADDRESS SPECIFIED BY THE
;VALUE OF THE SYMBOL .VBOOT.  THE .VBOOT ADDRESS SPACE IS NOT
;ADDRESSABLE UNTIL THE LABEL MAPPED AND ALL REFERENCES TO THE
;DATA LOCATIONS BEFORE THAT LABEL MUST BE OFFSET BY A "-.RDATA"
;TO MAKE THEM PHYSICAL/1 FOR 1 VIRTUAL ADDRESSES.  WHEN BOOT HAS
;TO MOVE ITSELF ELSEWHERE IN MEMORY, IT SIMPLY MAKES THE DESTINATION
;ADDRESSABLE, BLTS ITSELF, AND CHANGES THE MAPPING OF THE .VBOOT
;ADDRESS SPACE TO MAP THE NEW PHYSICAL MEMORY.  ALL THIS MEANS THAT
;MOST OF THE PROGRAM REALLY DOESN'T CARE WHERE IT IS IN MEMORY.
;WE JUST MAP IT APPROPRIATELY AND IT RUNS IN ITS OWN, UNCHANGING,
;VIRTUAL ADDRESS SPACE.
	SUBTTL	PARAMETER DEFINITIONS ;⊗ .CHBEL .CHCNH .CHTAB .CHLFD .CHVTB .CHFFD .CHCRT .CHCNU .CHCNZ .CHESC .CHDEL FL.RUB FL.OVW FL.WLD FL.RIB FL.EXR FL.ZER FL.IO FL.LDE FL.FFL FR.DEV FR.FIL FR.EXT FR.PTH FR.RBT FR.DMP FR.LOD FR.STA FR.1ST FR.ALL FX.CLR


;SYMBOLIC CHARACTER DEFINITIONS

.CHBEL==007	;BELL
.CHCNH==010	;BACKSPACE
.CHTAB==011	;TAB
.CHLFD==012	;LINE-FEED
.CHVTB==013	;VERTICAL TAB
.CHFFD==014	;FORM FEED
.CHCRT==015	;CARRIAGE RETURN
.CHCNU==025	;CONTROL U
.CHCNZ==032	;CONTROL Z
.CHESC==033	;ESCAPE
.CHDEL==177	;DELETE


;FLAGS IN S.  NOTE THAT THE FR.XXX FLAGS MUST BE IN THE SAME ORDER
;AS SWTTAB SINCE THE OFFSET INTO SWTTAB IS USED TO SET THE BIT IN S.

FL.RUB==1B0	;CURRENTLY PROCESSING RUBOUT
FL.OVW==1B1	;IGNORE UNPROCESSED DUMPS
FL.WLD==1B2	;DEVICE IS WILD
FL.RIB==1B3	;SKIP 1 BLOCK IN SELBLK SO THAT WE SKIP THE RIB
FL.EXR==1B4	;READING IN AN EXTENDED RIB
FL.ZER==1B5	;ALREADY ZEROED CORE
FL.IO==1B6	;1 IF DOING OUTPUT, 0 IF DOING INPUT
FL.LDE==1B7	;ERROR BEING PROCESSED WAS FROM LOAD, NOT DUMP
FL.FFL==1B8	;FOUND FILE IN FNDFIL

FR.DEV==1B18	;DEVICE SEEN
FR.FIL==1B19	;FILENAME SEEN
FR.EXT==1B20	;EXTENSION SEEN
FR.PTH==1B21	;PATH SEEN

FR.RBT==1B32	;/REBOOT SEEN
FR.DMP==1B33	;/DUMP SEEN
FR.LOD==1B34	;/LOAD SEEN
FR.STA==1B35	;/START SEEN
FR.1ST==1B35	;RIGHT-MOST BIT OF SWITCH BITS. SHIFT THIS BIT BY THE
		;OFFSET INTO SWTTAB TO SET THE APPROPRIATE SWITCH BIT
FR.ALL==FR.DEV!FR.FIL!FR.EXT!FR.PTH!FR.RBT!FR.DMP!FR.STA!FR.LOD
		;ALL PARSE BITS
FX.CLR==FL.RUB!FL.OVW!FL.WLD!FR.ALL ;BITS TO CLEAR ON ENTRY TO PARSE
;MONITOR PARAMETERS WHICH MUST AGREE WITH COMMON/COMMOD. ;⊗ HOMNAM HOMSNM HOMLUN HOMBSC HOMSCU HOMCNP HOMCLP HOMBPC HOMREF HOMMFD HOMCOD CODHOM HOMSLF RIBFIR RIBPPN RIBNAM RIBEXT RIBSIZ RIBSTS RIPDMP RIBXRA RIPNUB RIBCOD CODRIB RIBSLF BOOTSA BOOTWD LBNHOM LB2HOM LBOBAT LIMLVL MBTCOM MAXPGS .EPHSB
;
;HOME BLOCK DEFINITIONS

HOMNAM==0		;SIXBIT/HOM/
HOMSNM==4		;SIXBIT STRUCTURE NAME
HOMLUN==10		;LOGICAL UNIT NUMBER WITHIN FILE STRUCTURE
HOMBSC==14		;BLOCKS PER SUPERCLUSTER
HOMSCU==15		;SUPER CLUSTERS PER UNIT
HOMCNP==16		;BYTE POINTER TO CLUSTER COUNT IN RETRIEVAL PTR
HOMCLP==20		;BYTE POINTER TO CLUSTER ADDRESS IN RET. PTR
HOMBPC==21		;BLOCKS PER CLUSTER
HOMREF==23		;NON-ZERO IF STRUCTURE NEEDS REFRESHING
HOMMFD==46		;LOGICAL BLOCK NUMBER IN STR OF RIB FOR MFD
HOMCOD==176		;CONTAINS UNLIKELY CODE
CODHOM==707070		;THE CODE
HOMSLF==177		;SELF BLOCK POINTER


;RIB DEFINITIONS

RIBFIR==0		;AOBJN POINTER TO FIRST RETRIVAL POINTER IN RIB
RIBPPN==1		;PPN OF FILE
RIBNAM==2		;SIXBIT FILENAME
RIBEXT==3		;SIXBIT EXTENSION
RIBSIZ==5		;SIZE OF FILE IN WORDS
RIBSTS==17		;STATUS BITS
RIPDMP==100000		;THIS FILE CONTAINS AN UNPROCESSED DUMP
RIBXRA==34		;POINTER TO NEXT EXTENDED RIB
RIPNUB==400000		;NEW UNIT POINTER IN RETRIEVAL POINTER
RIBCOD==176		;CONTAINS UNLIKELY CODE
CODRIB==777777		;THE CODE
RIBSLF==177		;SELF BLOCK POINTER


;MISCELANEOUS DEFINITIONS

BOOTSA==21		;PHYSICAL ADDRESS FROM WHICH BOOT LOADED THE
			;  MONITOR.  USED TO FIND MONITOR FILESPEC
BOOTWD==22		;APRID OR CONI PAG, OF CPU ON WHICH BOOT WAS
			;  RUN.  ALSO USED AS CHANNEL COMMAND PAIR FOR
			;  RH10'S.
LBNHOM==1		;BLOCK ADDRESS OF FIRST HOME BLOCK
LB2HOM==12		;BLOCK ADDRESS OF SECOND HOME BLOCK
LBOBAT==1		;OFFSET OF BAT BLOCK FROM HOME BLOCK
LIMLVL==5		;NUMBER OF SFD'S
MBTCOM==411		;COMMUNICATIONS WORD IN LOW CORE FOR REBOOT
			;REQUESTS.  CONTAINS THE PHYSICAL PAGE NUMBER
			;OF WHERE TO PUT BOOT DURING REBOOT PROCESSING
MAXPGS==<FTKI10&↑D8192>!<FTKL10&↑D8192>!<FTKS10&↑D1024>
			;MAXIMUM NUMBER OF PAGES POSSIBLE IN MEMORY
.EPHSB==424		;KS10 HALT STATUS BLOCK ADDRESS
;MISCELANEOUS HARDWARE PARAMETERS ;⊗ IT.DON IT.BSY APRRST CLRAPR PDLLEN LINBFL BLKSIZ PAGSIZ MAXUNI P2BLSH B2WLSH W2BLSH P2WLSH W2PLSH .VBOOT .VPAG0 .VMOVE .VZERO .MBOOT .MPAG0 .MMOVE .MZERO

IT.DON==1B30		;KI10 CONI CTY, INPUT DONE
IT.BSY==1B31		;KI10 CONI CTY, OUTPUT BUSY
APRRST==<FTKI10&321300>!<FTKL10&327760>!<FTKS10&221700>
			;CONO BITS TO CLEAR THE WORLD
CLRAPR==<FTKI10&300>!<FTKL10&127700>!<FTKS10&021700>
			;CONO BITS TO CLEAR APR ERROR FLAGS


;MISCELANEOUS PARAMETERS

PDLLEN==↑D36		;SIZE OF PDL
LINBFL==↑D16		;SIZE OF COMMAND LINE BUFFER IN WORDS
BLKSIZ==200		;SIZE OF A DISK BLOCK
PAGSIZ==1000		;SIZE OF A PAGE
MAXUNI==↑D8		;MAX NUMBER OF UNITS ON A CONTROLLER
P2BLSH==2		;AMOUNT TO LSH A PAGE COUNT TO GET BLOCKS
B2WLSH==↑D7		;AMOUNT TO LSH A BLOCK COUNT TO GET WORDS
W2BLSH==-B2WLSH		;AMOUNT TO LSH A WORD COUNT TO GET BLOCKS
P2WLSH==↑D9		;AMOUNT TO LSH A PAGE NUMBER TO GET WORDS
W2PLSH==-P2WLSH		;AMOUNT TO LSH A WORD COUNT TO GET PAGES

.VBOOT==750000		;VIRTUAL ADDRESS AT WHICH MOST OF BOOT
			;  RUNS (AFTER CALL TO SETUP)
.VPAG0==730000		;PAGE 0 MAPPED THROUGH THIS VIRUAL ADDRESS
			;PAGE 1 MAPPED THROUGH .VPAG0+PAGSIZ
.VMOVE==732000		;FIRST VIRTUAL ADDRESS USED TO MOVE BOOT TO
			;  HIGH CORE
.VZERO==732000		;VIRTUAL ADDRESS USED TO ZERO CORE


DEFINE	VMAP(ADDR),<<ADDR/PAGSIZ>/2>

.MBOOT==VMAP(.VBOOT)	;LEFT HALF WORD IN EPT MAPPING .VBOOT
.MPAG0==VMAP(.VPAG0)	;LEFT HALF WORD IN EPT MAPPING .VPAG0
			;RIGHT HALF WORD MAPS .VPAG0+PAGSIZ
.MMOVE==VMAP(.VMOVE)	;LEFT HALF WORD IN EPT MAPPING .VMOVE
.MZERO==VMAP(.VZERO)	;LEFT HALF WORD IN EPT MAPPING .VZERO
IFN FTKL10!FTKI10,< ;⊗ CI.XDN CI.122 CI.1ER CI.1RA CI.2ER CI.2RA CO.XDN CO.XSX CO.XMI CO.1RB CO.1AE CO.2RB CO.2ME DO.XCR DO.XSR DI.XCE DI.XSM DI.XSB DO.XDS DO.XDT DO.XDC DO.1CR DO.2ST DO.XCL DO.XRP DO.XRD DO.XWT RH2TRA RH2JMP R2IOWL R2BCNT R2WCNT R1BCNT R1WCNT

;RH10/RH20 DEVICE DEPENDENT PARAMETERS

;CONI BITS
CI.XDN==10		;TRANSFER DONE (RH10/RH20)
CI.122==4000,,0		;22 BIT CHANNEL (RH10/DF10C)
CI.1ER==736320		;DBPE, FXCEP, CHNER, OVR, DRE, ILC, PSFAIL,
			;CBOV, RAE, BUSY (RH10)
CI.1RA==100		;RAE (RH10)
CI.2ER==515000		;DPE, LWCE, DR, RAE, DOE (RH20)
CI.2RA==4000		;RAE (RH20)

;CONO BITS
CO.XDN==10		;CLEAR DONE (RH10/RH20)
CO.XSX==20		;STOP TRANSFER (RH10/RH20)
CO.XMI==2000		;MASSBUS INIT (RH10/RH20)
CO.1RB==47		;CONI BITS TO RESTORE - AIE, PIA (RH10)
CO.1AE==40		;AIE (RH10)
CO.2RB==447		;CONI BITS TO RESTORE - MBE, AIE, PIA (RH20)
CO.2ME==400		;MASSBUS ENABLE (RH20)

;DATAI/DATAO BITS

DO.XCR==004400,,0	;DRIVE CONTROL REGISTER (RH10/RH20)
DO.XSR==010400,,0	;STATUS REGISTER (RH10/RH20)
  DI.XCE==40000		;COMPOSITE ERROR (RH10/RH20)
  DI.XSM==172777	;BIT MASK OF BITS TO CHECK FOR IN INITIALIZATION
  DI.XSB==10700		;LEGAL VALUE IN SR (MOL, DP, DR, VV)
DO.XDS==054000,,0	;BLOCK ADDRESS REGISTER, LR (RH10/RH20)
DO.XDT==060000,,0	;DRIVE TYPE REGISTER (RH10/RH20)
DO.XDC==124000,,0	;DESIRED CYLINDER REGISTER, LR (RH10/RH20)
DO.1CR==404000,,0	;CONTROL REGISTER (RH10)
DO.2ST==716200,,0	;STCR, LR, RCLP, STORE (RH20)
DO.XCL==11		;FUNCTION CODE FOR DRIVE CLEAR (RH10/RH20)
DO.XRP==21		;FUNCTION CODE FOR READIN PRESET (RH10/RH20)
DO.XRD==71		;FUNCTION CODE FOR READ (RH10/RH20)
DO.XWT==61		;FUNCTION CODE FOR WRITE (RH10/RH20)

;MISCELANEOUS

RH2TRA==1B0		;CHANNEL COMMAND OPCODE FOR TRANSFER (RH20)
RH2JMP==1B1		;CHANNEL COMMAND OPCODE FOR JUMP (RH20)
R2IOWL==↑D69		;NUMBER OF IOWDS TO ALLOCATE FOR THE LARGEST
			;POSSIBLE TRANSFER
R2BCNT==↑D15		;MAX NUMBER OF BLOCKS WHICH MAY BE SPECIFIED
			;IN ONE IOWD FOR AN RH20
R2WCNT==R2BCNT*BLKSIZ	;CORRESPONDING WORDCOUNT
R1BCNT==↑D127		;MAX NUMBER OF BLOCKS WHICH MAY BE SPECIFIED
			;IN ONE IOWD FOR AN RH10
R1WCNT==R1BCNT*BLKSIZ	;CORRESPONDING WORDCOUNT

>;END IFN FTKL10!FTKI10
IFN FTKS10,< ;⊗ SO.UPR SO.VFT SO.RBT SO.USR SO.UBI SI.UER SO.CS1 SI.RDY SI.S1E SO.WC SO.BA SO.DA SO.CS2 SO.DS SO.DSM SO.DSB SI.DT SI.DSK SO.DC SO.DCL SO.RIP SO.WRT SO.RED RSBCNT

;RH11 DEVICE DEPENDENT PARAMETERS

;UBA ADDRESSES/BITS

SO.UPR==763000		;UBA PAGING RAM ADDRESS
  SO.VFT==140000	;VALID+FAST XFER
  SO.RBT==100,,277	;BITS TO RESTORE IN CS1 AND UBA SR
SO.USR==763100		;UBA STATUS REGISTER
  SO.UBI==100		;UNIBUS INIT
  SI.UER==740000	;TIME OUT, BMD, BUS PAR, NXD

;DRIVE ADDRESSES/BITS

SO.CS1==776700		;CONTROL STATUS REGISTER 1
  SI.RDY==200		;READY AT END OF XFER
  SI.S1E==140000	;SC, TRE
SO.WC==776702		;WORD COUNT REGISTER
SO.BA==776704		;BUS ADDRESS REGISTER
SO.DA==776706		;DESIRED ADDRESS REGISTER
SO.CS2==776710		;CONTROL STATUS REGISTER 2
SO.DS==776712		;DRIVE STATUS REGISTER
  SO.DSM==172700	;MASK FOR BITS RETURNED
  SO.DSB==10700		;LEGAL VALUE (MOL, DP, DR, VV)
SI.DT==776726		;DRIVE TYPE REGISTER
  SI.DSK==20000		;DEVICE IS A DISK
SO.DC==776734		;DESIRED CYLINDER REGISTER

;MISCELLANEOUS

SO.DCL==11		;FUNCTION CODE FOR DRIVE CLEAR
SO.RIP==21		;FUNCTION CODE FOR READIN PRESET
SO.WRT==61		;FUNCTION CODE FOR WRITE
SO.RED==71		;FUNCTION CODE FOR READ

RSBCNT==↑D252		;MAX NUMBER OF BLOCKS WHICH MAY BE TRANSFERED
			;AT ONE TIME BY THE RH11

>;END IFN FTKS10
	SUBTTL	MACRO DEFINITIONS ;⊗ OFFSET OFFSET LABEL BTSLOC


;MACRO DEFINITIONS TO ALLOW ASSEMBLY TO BE PHASED STARTING AT
;.VBOOT

DEFINE	$PHASE,<
	  OFFSET==.-BOOTVA
	  OFFSET==.VBOOT+OFFSET
	  PHASE	OFFSET
	>


DEFINE	$DEPHASE,<
	  XLIST
	  LIT
	  LIST
	  DEPHASE
	>


DEFINE	BLK(LABEL,SIZE),<
	  LABEL==BTSLOC
	  BTSLOC==BTSLOC+SIZE
	  BLOCK	SIZE
	>


;MACRO TO BUILD THE BOOT VERSION STRING

DEFINE	VSTR(VER,EDT),<
ASCIZ/BOOT V'VER'(EDT)

/
	>
;MACROS TO HELP IN INSERTING ENTRIES INTO THE PAGE MAP ;⊗ ZZ ZZ

DEFINE	ONE41(FPAGE,LPAGE),<
	  ZZ==FPAGE
	  XLIST
	  REPEAT <<LPAGE-FPAGE+1>/2>,<
	    XWD	PM.ACC+PM.WRT+ZZ,PM.ACC+PM.WRT+ZZ+1
	    ZZ==ZZ+2
	  >
	  LIST
	>


DEFINE	INSLOC(FLOC,LLOC,INSTN),<
	  XLIST
	  REPEAT <LLOC-FLOC+1>,<
	    INSTN
	  >
	  LIST
	>


;MACRO TO CAUSE A PAUSE BETWEEN THE DATAO WHICH LOADS THE PREPARATION
;REGISTER AND THE DATAI WHICH READS THE VALUE FROM THE SPECIFIED
;REGISTER.

	DEFINE	STALL,<
	  IMULI	P,1
	  IFN FTKL10,<
	  XLIST
	  IMULI P,1
	  LIST
	  >
	>
	SUBTTL	DATA AREAS ;⊗ .RDATA BTSLOC EPTABS R2IOWD BTSLOC


;THE DATA AREA MUST BE THE FIRST THING IN THIS PROGRAM THAT GENERATES
;CODE TO INSURE THAT IT STARTS ON A PAGE BOUNDARY.  IN ADDITION,
;THE EPT MUST BE THE FIRST THING IN THE DATA AREA FOLLOWED IMMEDIATELY
;BY THE BLOCKS FOR HOM, RIB, AND BUF, FOR THE SAME REASON.  NOTE
;THAT IF ANY OF THE LAST THREE BLOCKS ARE SPLIT ACROSS A PAGE BOUNDARY
;THE I/O SUBROUTINES WILL NOT (NECESSARILY) WORK.

.RDATA==.VBOOT-.	;RELOCATABLE ADDRESS OF START OF DATA
BTSLOC==.VBOOT		;INITIALIZE MACROS

EPTABS:			;UNMAPPED ADDRESS OF EPT
BLK(EPT,0)		;PUT THIS HERE SO IT STARTS ON A PAGE BOUNDARY
	BLOCK	200		;0-177 MISCELANEOUS BLOCKS NOT FILLED IN
	ONE41	(400,777)	;200-377=PAGES 400-777 IN EXEC MAP
	ONE41	(340,377)	;400-417=PAGES 340-377 IN USER MAP
IFN FTKI10,<
	JSR	PFTRAP		;420=PAGE FAIL TRAP INSTRUCTION ON KI10
>
IFN FTKL10!FTKS10,<
	BLOCK	1		;420=UNUSED ON KL OR KS
>
	JFCL			;421=ARITHMETIC OVERFLOW TRAP INSTRUCTION
	JRST	TRAP		;422=PDL OVERFLOW TRAP INSTRUCTION
	JRST	TRAP		;423=TRAP 3 TRAP INSTRUCTION
	BLOCK	4		;424-427 MUUO LOCATIONS
	INSLOC	(430,437,<EXP TRAP>) ;430-437=MUUO NEW PC WORDS
	BLOCK	40		;440-477=UNUSED
	BLOCK	2		;500-501=PAGE FAIL LOCATIONS ON KL AND KS
IFN FTKI10,<
	BLOCK	1		;502=UNUSED ON KI10
>
IFN FTKL10!FTKS10,<
	EXP	PFTRAP		;502=NEW PC WORD ON KL AND KS
>
	BLOCK	75		;503-577=UNUSED
IFN FTKI10,<
	BLOCK	160		;600-757=UNUSED ON KI10
>
IFN FTKL10!FTKS10,<
	ONE41	(0,337)		;600-757=PAGES 0-377 ON KL AND KS
>
	BLOCK	20		;760-777=UNUSED

IFN FTKL10,<
R2IOWD==EPT+PAGSIZ-R2IOWL ;WHERE TO PUT RH20 IOWDS
>

BTSLOC==BTSLOC+PAGSIZ		;UPDATE PHASED ASSEMBLY COUNTER
BLK(HOM,BLKSIZ)		;HOM BLOCK FOR CURRENT UNIT ;⊗ SWTVLV SWTVLL FILSPE NXMTBE
BLK(RIB,BLKSIZ)		;RIB BLOCK FOR CURRENT FILE
BLK(BUF,BLKSIZ)		;WORK BUFFER

;THE FOLLOWING LOCATIONS MUST REMAIN IN THIS ORDER.  (SEE BOOTFX IN
;ONCE)

BLK(FILSPC,0)		;FIRST WORD CLEARED EACH TIME THROUGH PARSE
BLK(DEV,1)		;DEVICE NAME
BLK(FILNAM,1)		;FILENAME
BLK(EXT,1)		;EXTENSION
BLK(PTHBLK,7)		;PATH BLOCK

;END OF ORDER DEPENDENT LOCATIONS


SWTVLV:
BLK(SWTVAL,0)		;START OF BLOCK OF SWITCH VALUES
BLK(STSA,1)		;START ADDRESS GIVEN IN /START
SWTVLL==.-SWTVLV
FILSPE==BTSLOC-1	;END OF AREA TO CLEAR EACH TIME THROUGH PARSE

BLK(EPTADR,1)		;PHYSICAL ADDRESS OF OUR EPT
BLK(CPEBR,1)		;ARGUMENT TO CHANGE THE EPT TO IT'S CURRENT VALUE
BLK(MEMPSZ,1)		;NUMBER OF PAGES IN MEMORY
BLK(LUNPOS,1)		;LOGICAL UNIT NUMBER WITHIN STR
BLK(DRVBPC,1)		;BLOCKS/CYLINDER ON THIS UNIT \*** KEEP
BLK(DRVBPT,1)		;BLOCKS/TRACK ON THIS UNIT    /*** TOGETHER
BLK(BLKCNT,1)		;NUMBER BLOCKS LEFT IN THIS GROUP
BLK(BLKADR,1)		;CURRENT BLOCK ADDRESS
BLK(BLKNUM,1)		;CURRENT RELATIVE BLOCK NUMBER IN FILE
BLK(SAVFIR,1)		;COPY OF RIBFIR FROM CURRENT RIB
BLK(SAVSIZ,1)		;COPY OF RIBSIZ FROM CURRENT RIB
BLK(BTSPDL,PDLLEN)	;PUSH DOWN LIST
BLK(CMDPTR,1)		;BYTE POINTER TO COMMAND BUFFER
BLK(CMDBUF,LINBFL)	;COMMAND LINE BUFFER
BLK(NXMTAB,<MAXPGS/↑D36>+1) ;OUR COPY OF NXMTAB
NXMTBE==BTSLOC-1	;END OF NXMTAB
;HERE AFTER BEING LOADED INTO MEMORY.  WE ARE (PROBABLY) RUNNING ;⊗ BOOT
;UNPAGED AT THIS POINT SO WE MUST DO SOMETHING ABOUT THAT FIRST.

BOOT:	CONO	APR,APRRST	;BLAST THE PROCESSOR
IFN FTKL10,<
	CONO	APR,APRRST	;-20F STARTS BOOTSTRAPS AT ENTRY+1
>
	CONO	PI,PI.CPI!PI.OFF ;BLAST THE PI SYSTEM
IFN FTKI10,<
	MOVEI	T1,PG.LEB!PG.EAT!<EPTABS/PAGSIZ> ;GET BITS TO SET THE EBR
	MOVSI	T4,<(PG.LUB)>!<EPTABS/PAGSIZ> ;AND TO SET THE UBR
	DATAO	PAG,T1		;TURN ON PAGING, MAP US 1 FOR 1
	DATAO	PAG,T4		;SET THE UPT TO THE SAME PAGE
>
IFN FTKL10,<
	MOVEI	T1,LG.TEN!<EPTABS/PAGSIZ> ;GET BITS TO SET THE EBR
	MOVSI	T4,(LG.LAB!LG.LPC!LG.LUB) ;FLAG BITS TO LOAD THE UBR
	HRRI	T4,LG.IAM!<EPTABS/PAGSIZ> ;AND THE PAGE NUMBER
	CONO	PAG,(T1)	;TURN ON PAGING, MAP US 1 FOR 1
	DATAO	PAG,T4		;SET THE UPT TO THE SAME PAGE
	CONO	DTE0,PILDEN!0	;TURN OFF DTE PIA
>
IFN FTKS10,<
	WREBR	0		;TURN OFF PAGING, MAKE THE KS HAPPY
	MOVEI	T1,SG.TEN!<EPTABS/PAGSIZ> ;GET BITS TO SET THE EBR
	MOVSI	T4,(SG.LAB!SG.LUB) ;FLAG BITS TO LOAD THE UBR
	HRRI	T4,<EPTABS/PAGSIZ> ;AND THE PAGE NUMBER
	WREBR	(T1)		;TURN ON PAGIN, MAP US 1 FOR 1
	WRUBR	T4		;SET THE UPT TO THE SAME PAGE
	MOVEI	T2,.EPHSB	;GET HALT STATUS BLOCK ADDRESS
	WRHSB	T2		;WRITE IT
>
	MOVEM	T1,CPEBR-.RDATA ;STORE BITS TO CHANGE EBR FOR LATER
	MOVEI	T2,PM.ACC!PM.WRT!0 ;MAKE PAGE 0 AND 1 ADDRESSABLE
	HRLI	T2,1(T2)	;AS VIRTUAL ADDRESSES .VPAG0
	MOVSM	T2,EPT+.MPAG0-.RDATA ;AND .VPAG0+PAGSIZ IN OUR MAP
	MOVEI	T2,EPTABS	;GET PHYSICAL ADDRESS OF OUR EPT
	MOVEM	T2,EPTADR-.RDATA ;STORE FOR LATER
	LSH	T2,W2PLSH	;CONVERT TO A PAGE NUMBER
	HRLI	T2,-BOOPGS	;MAKE AOBJN POINTER
	TRO	T2,PM.ACC+PM.WRT ;SET FLAG BITS
	MOVSI	T3,(POINT 18,0)	;BUILD BYTE POINTER TO EPT (NO LITERAL
	HRRI	T3,EPT+.MBOOT-.RDATA  ; TO GET AROUND A LINK BUG)
	IDPB	T2,T3		;MAP BOOT IN .VBOOT ADDRESS SPACE
	AOBJN	T2,.-1		;  ADDRESS SPACE
	MOVE	T2,CHGEBR-.RDATA ;GET INSTRUCTION TO CHANGE THE EBR
	MOVSI	T3,(JRST)	;SETUP JRST TO GET BACK AFTER
	HRRI	T3,MAPPED	;  WE'RE MAPPED
	JRST	T2		;CHANGE THE EBR, COME BACK MAPPED
;HERE WHEN THE .VBOOT ADDRESS SPACE HAS BEEN MAPPED TO DO SOME ONCE ;⊗ MAPPED
;ONLY INITIALIZATION BEFORE FALLING INTO RLDMON.

	$PHASE


MAPPED:	MOVEI	P,BTSPDL	;SETUP A PDL
IFN FTKL10,<
	SETZM	EPT+DTEEPW	;CLEAR DTE EXAMINE/PROTECTION WORD
	SETZM	EPT+DTEMTI	;CLEAR INPUT READY FLAG
	MOVSI	T3,DT.ESP	;BIT TO CAUSE -20F TO ENTER SECONDARY
	HRRI	T3,DTEFLG	;IN THIS WORD
	PUSHJ	P,DODTE		;EXECUTE THE COMMAND
>
IFN FTKS10,<
	SETZM	.VPAG0+CTYIWD	;CLEAR INPUT AVAILABLE WORD
	SETZM	.VPAG0+CTYOWD	;AND OUTPUT PRESENT WORD
	SETZM	.VPAG0+RLWORD	;AND FLAGS WORD
>
	MOVEI	S,0		;ZERO FLAGS
	PUSHJ	P,SUNXMT	;LOOK AT MEMORY AND SETUP NXMTAB
	MOVEI	T1,VERMSG	;POINT AT VERSION STRING
	PUSHJ	P,PRMSG		;TELL HIM THAT WE'RE HERE
;;	PJRST	RLDMON		;FALL INTO RLDMON
;ROUTINE TO PROMPT THE USER AND DUMP/LOAD/RELOAD THE MONITOR.  CALL ;⊗ RLDMON RLDMO1 RLDMO2
;AFTER SETTING UP THE MAP SO THAT WE ARE RUNNING IN THE .VBOOT ADDRESS
;SPACE.  EXITS TO THE START ADDRESS OF THE NEW MONITOR.
;CALL:	PJRST	RLDMON


RLDMON:	MOVEI	P,BTSPDL	;SETUP PDL AGAIN IN CASE OF TRAP
	MOVEI	T1,[ASCIZ/BOOT>/] ;OUR PROMPT
	PUSHJ	P,REDLIN	;TYPE IT AND READ IN RESPONSE
	PUSHJ	P,PARSE		;PARSE THE COMMAND
	  JRST	RLDMON		;SYNTAX ERROR
	TRNE	S,FR.DMP	;/DUMP SEEN?
	JRST	[PUSHJ P,DODUMP ;YES, TAKE A DUMP
		 JRST  RLDMON]	;AND GO BACK AROUND
	TRNE	S,FR.STA	;/START SEEN?
	TRNE	S,FR.ALL-FR.STA	;AND NOTHING ELSE?
	CAIA			;NO
	JRST	RLDMO1		;YES, JUST START UP MONITOR
	PUSHJ	P,DOLOAD	;LOAD NEW MONITOR
	  JRST	RLDMON		;ERROR DETECTED
	TRNE	S,FR.LOD	;/LOAD SPECIFIED?
	JRST	RLDMON		;YES, DON'T START
RLDMO1:	TRNE	S,FR.RBT	;THIS A /REBOOT REQUEST?
	JRST	RLDMO2		;YES, DON'T CHANGE CORE
	MOVE	T1,EPTADR	;GET PHYSICAL ADDRESS OF EPT
	ADDI	T1,FILSPC-EPT-140 ;COMPUTE BOOTSA POINTER
	TLO	T1,(1B0)	;SET SIGN BIT SO MONITOR CAN TELL IT'S BOOT
	MOVEM	T1,.VPAG0+BOOTSA ;SO THAT BOOTFX CAN FIND THE MONITOR NAME
IFN FTKL10!FTKS10,<
	APRID	.VPAG0+BOOTWD	;STORE SERIAL NUMBER FOR SYSTRT
>
IFN FTKI10,<
	CONI	PAG,.VPAG0+BOOTWD ;DITTO FOR KI
>
	MOVE	17,[CONO APR,200000] ;STORE CONO APR,200000 SO THAT
	SKIPA	T2,[MOVEM 17,FILSPC-140+1000] ;CONSISTENCY CHECKS WORK
RLDMO2:	MOVSI	T2,(JFCL)	;DON'T DO ANYTHING IF FROM REBOOT
	SKIPN	T4,STSA		;START ADDRESS SPECIFIED ON /START?
	HRRZ	T4,.VPAG0+.JBSA## ;NO, USE ADDRESS FROM FILE
	HRLI	T4,(JRST)	;MAKE IT A JRST
	MOVE	T3,CHGEBR	;GET INSTRUCTION TO CHANGE THE EBR
IFN FTKI10,<
	MOVEI	T1,PG.LEB	;TURN OFF PAGING KI STYLE
>
IFN FTKL10!FTKS10,<
	MOVEI	T1,0		;TURN OFF PAGING KL/KS STYLE
>
	JRST	T2		;TURN OFF PAGING AND START NEW MONITOR
CHGEBR: ;⊗ CHGEBR CHGUBR VERMSG
IFN FTKI10,<
	DATAO	PAG,T1		;CHANGE THE EBR
>
IFN FTKL10,<
	CONO	PAG,(T1)	;CHANGE THE EBR
>
IFN FTKS10,<
	WREBR	(T1)		;CHANGE THE EBR
>

CHGUBR:
IFN FTKI10!FTKL10,<
	DATAO	PAG,T4		;CHANGE THE UBR
>
IFN FTKS10,<
	WRUBR	T4		;CHANGE THE UBR
>


;BUILD THE BOOT VERSION MESSAGE

VERMSG:	VSTR	(\BOOVER,\BOOEDT)
	SUBTTL	DUMP MONITOR ;⊗ ASKSTR DODUMP DODUM1 DODUM2 DODUM3 DODUM4


;ROUTINE TO DUMP THE SYSTEM. CALL WITH INITIAL FILESPEC ON
;WHICH TO DUMP IN THE FILESPEC AREA.  ASKS THE USER FOR A NEW
;FILESPEC IF ERRORS ARE DETECTED.
;CALL:	PUSHJ	P,DODUMP
;RETURN+1 ALWAYS

ASKSTR:	MOVEI	T1,[ASCIZ/Filespec on which to dump: /]
	PUSHJ	P,REDLIN	;ASK WHERE HE WANTS THE DUMP
	PUSHJ	P,PARSE		;PARSE THE COMMAND
	  JRST	ASKSTR		;TRY AGAIN
	TRNN	S,FR.ALL	;SEE ANYTHING AT ALL?
	POPJ	P,		;NO, LONE CR MEANS NO DUMP
	TRO	S,FR.DMP	;MAKE SURE DUMP FLAG IS SET

DODUMP:	MOVE	T1,[SIXBIT/CRASH/] ;DEFAULT FILENAME IS CRASH
	TRNN	S,FR.FIL	;SEE A FILENAME?
	MOVEM	T1,FILNAM	;NO, USE DEFAULT
	TLNN	S,(FL.WLD)	;WILD STR?
	JRST	DODUM2		;NO, USE THE ONE HE SAID
	MOVE	P1,['DSKA  '-10000] ;GET DISK NAME TO INCREMENT TO DSKA
DODUM1:	ADDI	P1,10000	;STEP TO NEXT DISK NAME
	CAMN	P1,[SIXBIT/DSKO/] ;LOOKED AT THE LAST ONE?
	JRST	DODUM4		;YES, GIVE UP
	MOVEM	P1,DEV		;SAVE NAME OF DEVICE
DODUM2:	TLZA	S,(FL.OVW)	;DON'T ALLOW OVERWRITING
DODUM3:	TLO	S,(FL.OVW)	;OVERWRITE IF HE SAYS TO
	PUSHJ	P,DUMP		;TRY TO DUMP THE MONITOR
	  JRST	DMPERR		;FAILED, ANALYZE ERROR AND TRY TO RECOVER
	POPJ	P,		;COMPLETED SUCCESSFULLY, RETURN
DODUM4:	MOVEI	T1,[ASCIZ/?Unable to find a file on which to dump
/]
	PUSHJ	P,PRMSG		;PRINT MESSAGE
	MOVEI	T1,[ASCIZ/Do you want to keep this dump? /]
	PUSHJ	P,ASKYN		;ASK HIM
	  POPJ	P,		;HE SAYS NO
	JRST	ASKSTR		;ASK ON WHAT STR TO DUMP
;HERE IF AN ERROR IS DETECTED IN THE DUMP OR LOAD.  USE THE ERROR ;⊗ LODERR DMPERR DMPER1 DMPER2 DMPER3
;CODE RETURNED IN T1 TO INDEX INTO EMSTAB AND PRINT A MESSAGE.
;FOR DUMP, INDEX INTO DMPDSP AND DISPATCH TO THE ROUTINE TO
;HANDLE THE ERROR.

LODERR:	TLOA	S,(FL.LDE) 	;FLAG LOAD ERROR
DMPERR:	TLZ	S,(FL.LDE)	;CLEAR BIT FOR DUMP ERRORS
	TLNE	S,(FL.WLD)	;WILD STRUCTURE?
	TLNE	S,(FL.FFL)	;YES, DID WE FIND THE FILE ON THIS STR?
	JRST	DMPER1		;YES, PROCEED NORMALLY
	CAIG	T1,FNFOFS	;NO, IS THIS ERROR JUST FILE OR STR NOT FOUND?
	JRST	DMPER2		;YES, DON'T PRINT MESSAGE
DMPER1:	PUSH	P,T1		;SAVE CODE FOR LATER
	HRRZ	T1,EMSTAB(T1)	;GET MESSAGE ADDRESS
	PUSHJ	P,PRMSG		;PRINT IT
	PUSHJ	P,PRFILE	;PRINT FILENAME
	PUSHJ	P,PRCRLF	;END THE LINE
	POP	P,T1		;RESTORE ERROR CODE
DMPER2:
IFN FTKI10,<
	CONSZ	APR,IP.PAR!IP.NXM ;NXM OR PARITY ERROR?
>
IFN FTKL10,<
	CONSZ	APR,LP.SBE!LP.NXM!LP.PAR ;NXM OR PARITY ERROR?
>
IFN FTKS10,<
	CONSZ	APR,SP.NXM!SP.HMP ;NXM OR PARITY ERROR?
>
	JRST	DMPER3		;YES
	TLNN	S,(FL.LDE)	;SKIP IF LOAD ERROR
	SKIPA	T1,DMPDSP(T1)	;GET DISPATCH ADDRESSES FOR DUMP
	MOVE	T1,LODDSP(T1)	;DITTO FOR LOAD
	TLNN	S,(FL.WLD)	;DOING WILD STR?
	MOVSS	T1		;YES, USE LH DISPATCH ADDRESSES
	JRST	(T1)		;GO RECOVER

;HERE ON A NXM OR PARITY ERROR DETECTED IN THE CONI APR TO PRINT THE
;APR STATUS AND GIVE UP.

DMPER3:	MOVEI	T1,[ASCIZ/?NXM or memory parity error detected/]
	PUSHJ	P,PRMSG		;TELL WHAT HAPPENED
	PUSHJ	P,PRTAPR	;PRINT APR STATUS
	CONO	APR,CLRAPR	;RESET THE BITS
	POPJ	P,		;AND GIVE UP
;TABLE OF ERROR MESSAGES INDEXED BY THE ERROR CODE RETURNED IN T1. ;⊗ EMSTAB FNFOFS EMSTBL DMPDSP DMPDSL LODDSP LODDSL STRFUL
;THE STRUCTURE NOT FOUND AND FILE NOT FOUND ERRORS MUST BE THE FIRST
;IN THE TABLE BEFORE THE LABEL FNFOFS SO THAT WE CAN AVOID PRINTING
;A FILE/STRUCTURE NOT FOUND MESSAGE FOR EVERY STRUCTURE WHEN THE
;OPERATOR SPECIFIES A WILD STRUCTURE NAME.

EMSTAB:	[ASCIZ/%Structure not found for /]
	[ASCIZ/%File not found /]
FNFOFS==.-EMSTAB-1
	[ASCIZ/%Unprocessed dump on /]
	[ASCIZ/%Unexpected end-of-file on /]
	[ASCIZ\%I/O error on \]
	[ASCIZ/%Bad directory format for /]
	[ASCIZ/%Memory configuration too complicated for /]
	[ASCIZ/%Not a REBOOTable dump /]
EMSTBL==.-EMSTAB


;DISPATCH TABLES INDEXED BY ERROR CODE.  LH GIVES THE DISPATCH ADDRESS
;IF AN EXPLICIT STRUCTURE WAS GIVEN, RH GIVES THE DISPATCH ADDRESS IF
;THE STRUCTURE WAS WILD (DSKA-DSKO)

DMPDSP:	XWD	ASKSTR,DODUM1	;STRUCTURE NOT FOUND
	XWD	ASKSTR,DODUM1	;FILE NOT FOUND
	XWD	STRFUL,DODUM1	;UNPROCESSED DUMP
	XWD	ASKSTR,DODUM1	;UNEXPECTED EOF
	XWD	ASKSTR,DODUM1	;I/O ERROR
	XWD	ASKSTR,DODUM1	;BAD DIRECTORY FORMAT
	XWD	ASKSTR,DODUM1	;MEMORY CONFIGURATION TOO COMPLICATED
	XWD	ASKSTR,DODUM1	;NOT A REBOOTABLE CRASH
DMPDSL==.-DMPDSP

LODDSP:	XWD	CPOPJ,DOLOA1	;STRUCTURE NOT FOUND
	XWD	CPOPJ,DOLOA1	;FILE NOT FOUND
	XWD	CPOPJ,DOLOA1	;UNPROCESSED DUMP
	XWD	CPOPJ,DOLOA1	;UNEXPECTED EOF
	XWD	CPOPJ,DOLOA1	;I/O ERROR
	XWD	CPOPJ,DOLOA1	;BAD DIRECTORY FORMAT
	XWD	CPOPJ,DOLOA1	;MEMORY CONFIGURATION TOO COMPLICATED
	XWD	CPOPJ,DOLOA1	;NOT A REBOOTABLE CRASH
LODDSL==.-LODDSP


IF2 <IFN EMSTBL-DMPDSL+LODDSL-ERRTBL,<
PRINTX ?Discrepency in lengths of EMSTAB, DMPDSP, LODDSP, ERRTAB
>>


;HERE IF AN EXPLICIT STR WAS GIVEN AND AN UNPROCESSED DUMP WAS FOUND
;ON THAT STR.

STRFUL:	MOVEI	T1,[ASCIZ/Do you want to overwrite it? /]
	PUSHJ	P,ASKYN
	  JRST	ASKSTR
	JRST	DODUM3
;ROUTINE TO DUMP THE MONITOR ONTO THE CRASH FILE SPECIFIED IN THE ;⊗ DUMP DUMP1 DUMP2
;COMMAND STRING.  DOES 5 ONE BLOCK TRANSFERS TO WRITE THE 4 BLOCKS
;OF THE DIRECTORY PLUS WORDS 0-177 OF PAGE 0 (SINCE THE RH20 CAN'T
;READ/WRITE ADDRESS 0) AND THEN DOES AS FEW TRANSFERS AS NECESSARY
;FOR EACH GROUP POINTER IN THE RIB.  (GENERALLY ONLY 1).  CALL WITH
;STRUCTURE NAME IN DEV.
;CALL:	PUSHJ	P,DUMP
;RETURN+1 IF ERROR DETECTED WITH ERROR CODE IN T1
;RETURN+2 IF SUCCESSFUL

DUMP:	PUSHJ	P,SAVE2		;SAVE P1-P2
	PUSHJ	P,FNDFIL	;FIND CRASH FILE FOR THIS STR
	  POPJ	P,		;NOT FOUND
	MOVEI	T1,[ASCIZ/[Dumping on /]
	PUSHJ	P,PRMSG		;TELL THE OPERATOR WHAT
	PUSHJ	P,PRFILE	;  WE'RE DOING
	PUSHJ	P,PRRBCR	;END THE LINE
	MOVEI	T1,RIPDMP	;GET "UNPROCESSED DUMP BIT"
	TLNN	S,(FL.OVW)	;DOES CALLER CARE?
	TDNN	T1,RIB+RIBSTS	;YES, IS BIT SET IN RIB?
	CAIA			;NO, OR DOESN'T CARE
	JRST	UPDERR		;YES, GIVE ERROR RETURN
	IORM	T1,RIB+RIBSTS	;SET BIT IN RIB
	PUSHJ	P,WRTRIB	;REWRITE RIB
	  POPJ	P,		;FAILED
	PUSHJ	P,CLRBUF	;CLEAR BUFFER AREA
	MOVSI	P3,-BLKSIZ	;MAKE AOBJP POINTER TO BUF
	MOVEI	P4,1		;FIRST FILE PAGE IS 1
	MOVEI	P2,0		;FIRST CORE PAGE IS 0
DUMP1:	PUSHJ	P,FNDPGS	;FIND NEXT GROUP OF CONTIGUOUS PAGES
	JUMPLE	P1,DUMP3	;DONE IF NONE FOUND
	MOVE	T1,P1		;COPY NUMBER OF PAGES TO T1
	SUBI	T1,1		;REPEAT COUNT FOR LAST HUNK
	ROT	T1,-↑D9		;NUMBER OF 256K HUNKS+REPEAT COUNT IN LH
	MOVEI	T2,1(T1)	;T2:=NUMBER OF DESCRIPTORS
DUMP2:	AOBJP	P3,MCCERR	;GO IF TOO MANY DESCRIPTORS
	HRRZM	P4,BUF(P3)	;STORE FILE PAGE NUMBER IN BUF
	MOVEI	T3,(P2)		;COPY CORE PAGE NUMBER TO T3
	HRLI	T3,770βX00	;512 PAGES IN THIS HUNK
	AOBJP	P3,MCCERR	;GO IF TOO MANY DESCRIPTORS
	MOVEM	T3,BUF(P3)	;STORE IN BUFFER
	ADDI	P2,<↑D256*↑D1024>/PAGSIZ ;INCR CORE PAGE
	ADDI	P4,<↑D256*↑D1024>/PAGSIZ ;DITTO FOR FILE PAGE
	SOJG	T2,DUMP2	;LOOP FOR ALL DESCRIPTORS
	HLLM	T1,BUF(P3)	;CORRECT REPEAT COUNT IN LAST DESCRIPTOR
	LSH	T1,-<↑D9+↑D18>	;RIGHT JUSTIFY REPEAT COUNT
	MOVNI	T1,-777(T1)	;HAVE TO BACK OFF ON CORE AND FILE PAGE
	SUBI	P2,(T1)		;  NUMBERS TO REFLECT THE (POSSIBLY)
	SUBI	P4,(T1)		;  PARTIAL ALLOCATION IN THE LAST DESCRIPTOR
	JRST	DUMP1		;LOOP FOR MORE
DUMP3:	MOVE	T1,[SV.END,,1]	;GET END OF DESCRIPTOR MARKER ;⊗ DUMP3 DUMP4 DUMP5 DUMP6
	AOBJP	P3,MCCERR	;GO IF TOO MANY DESCRIPTORS
	MOVEM	T1,BUF(P3)	;STORE IN BUFFER
	HRLI	P3,SV.DIR	;MAKE P3 BE 1ST WORD OF DIRECTORY
	MOVEM	P3,BUF		;AND STORE IT THERE
	PUSHJ	P,WRTBUF	;WRITE BUFFER TO FILE
	  POPJ	P,		;NO POINTERS OR WRITE FAILURE
	PUSHJ	P,CLRBUF	;CLEAR BUFFER AGAIN
	MOVEI	P1,3		;NEED TO WRITE 3 BLOCKS OF ZEROS
DUMP4:	PUSHJ	P,WRTBUF	;  TO COMPLETE DIRECTORY
	  POPJ	P,		;NO POINTERS OR WRITE FAILURE
	SOJG	P1,DUMP4	;LOOP FOR ALL
	MOVE	T1,[.VPAG0,,BUF] ;SETUP TO BLT WORD 0-177 TO BUF
	BLT	T1,BUF+BLKSIZ-1 ;DO SO
	PUSHJ	P,WRTBUF	;WRITE IT
	  POPJ	P,		;NO POINTERS OR WRITE FAILURE
	MOVEI	P2,0		;START WITH ADDRESS 0
DUMP5:	LSH	P2,W2PLSH	;CONVERT TO PAGE NUMBER
	PUSHJ	P,FNDPGS	;FIND NEXT GROUP OF CONTIGUOUS PAGES
	JUMPLE	P1,CPOPJ1	;DONE IF NO MORE
	LSH	P2,P2WLSH	;CONVERT BACK TO ADDRESS
	LSH	P1,P2BLSH	;CONVERT PAGES TO BLOCKS
	JUMPN	P2,DUMP6	;GO IF NOT DOING PAGE ZERO
	ADDI	P2,BLKSIZ	;COMPENSATE FOR WORDS 0-177
	SUBI	P1,1		;  WHICH WERE WRITTEN ABOVE
DUMP6:	JUMPLE	P1,DUMP5	;LOOP IF NO MORE BLOCKS IN THIS CHUNK
	MOVE	T1,P1		;COPY NUMBER OF BLOCKS WE WANT TO XFER
	PUSHJ	P,SELBLK	;SETUP TO DO THAT MANY
	  JRST	EOFERR		;RAN OUT OF POINTERS
	MOVE	R,P2		;START AT THIS ADDRESS
	MOVE	P1,T1		;COPY NUMBER LEFT INTO P1 FOR LOOP TEST
	MOVE	T1,M		;GET NUMBER OF BLOCKS WE CAN DO
	LSH	T1,B2WLSH	;CONVERT TO WORDS
	ADD	P2,T1		;INCREMENT ADDRESS FOR NEXT TIME
	PUSHJ	P,@WRTTAB(W)	;DO THE WRITE
	  JRST	IOFERR		;WRITE ERROR
	JRST	DUMP6		;LOOP FOR ALL OF CORE
	SUBTTL	RELOAD MONITOR ;⊗ DOLOAD DOLOA1 DOLOA2 DOLOA3


;ROUTINE TO RELOAD THE MONITOR FROM A FILE ON DISK.  CALL WITH
;THE FILESPEC FROM WHICH TO LOAD SETUP IN THE FILESPEC AREA.
;CALL:	PUSHJ	P,DOLOAD
;RETURN+1 IF ERRORS DETECTED WITH MESSAGE ALREADY ISSUED
;RETURN+2 IF LOAD WAS SUCCESSFUL

DOLOAD:	MOVE	T1,[SIXBIT/SYSTEM/] ;DEFAULT FILENAME IS SYSTEM
	TRNE	S,FR.RBT	;UNLESS A /REBOOT REQUEST
	MOVE	T1,[SIXBIT/CRASH/] ;IN WHICH CASE FILENAME IS CRASH
	TRNN	S,FR.FIL	;SEE A FILENAME?
	MOVEM	T1,FILNAM	;NO, USE DEFAULT
	TLNN	S,(FL.WLD)	;WILD STR?
	JRST	DOLOA2		;NO, USE THE ONE HE GAVE
	MOVE	P1,['DSKA  '-10000] ;GET FIRST DISK NAME
DOLOA1:	ADDI	P1,10000	;STEP TO NEXT DISK NAME
	CAMN	P1,[SIXBIT/DSKO/] ;LOOKED AT THEM ALL?
	JRST	DOLOA3		;YES, GIVE UP
	MOVEM	P1,DEV		;STORE STR NAME
DOLOA2:	PUSHJ	P,LOAD		;LOAD IT
	  JRST	LODERR		;GIVE ERROR MESSAGE AND RETURN
	JRST	CPOPJ1		;GIVE SKIP RETURN
DOLOA3:	MOVEI	T1,[ASCIZ/?No file found on any structure
/]
	PJRST	PRMSG		;GIVE ERROR MESSAGE AND RETURN
;ROUTINE TO LOAD A NEW MONITOR INTO CORE. CALL WITH THE FILESPEC AREA ;⊗ LOAD LOAD1 LOAD2 LOAD3 LOAD4 LOAD5 LOAD6 LOAD7
;CONTAINING THE FILE TO BE LOADED.
;CALL:	PUSHJ	P,LOAD
;RETURN+1 IF ERROR DETECTED WITH ERROR CODE IN T1
;RETURN+2 IF SUCCESSFUL

LOAD:	PUSHJ	P,SAVE2		;SAVE P1-P2
	PUSHJ	P,FNDMON	;FIND THE MONITOR, READ EXE DIRECTORY
	  POPJ	P,		;FAILED, RETURN CODE IN T1
	PUSHJ	P,FINDHI	;FIND PHYSICAL PAGE # OF TOP OF CORE
	PUSHJ	P,MOVBTS	;MOVE US TO THE TOP OF CORE
	TRNE	S,FR.RBT	;THIS A REBOOT?
	SKIPA	T1,[[ASCIZ/[Reloading from /]] ;YES, CHANGE THE MESSAGE
	MOVEI	T1,[ASCIZ/[Loading from /]
	PUSHJ	P,PRMSG		;TELL WHAT'S HAPPENING
	PUSHJ	P,PRFILE	;PRINT FILENAME
	PUSHJ	P,PRRBCR	;END THE LINE
	MOVEI	P3,0		;START WITH CORE ADDRESS OF ZERO
LOAD1:	LDB	P2,[POINT 9,1(P1),8] ;GET REPEAT COUNT FOR THIS ENTRY
	ADDI	P2,1		;MAKE IT TOTAL PAGE COUNT
	LSH	P2,P2BLSH	;COMPUTE BLOCK COUNT
	HRRZ	P4,0(P1)	;GET FILE PAGE NUMBER
	LSH	P4,P2BLSH	;COMPUTE FILE BLOCK NUMBER
	JUMPE	P4,[LSH  P2,B2WLSH ;IF ALLOCATED BUT ZERO PAGE, COMPUTE
		    ADD  P3,P2	;  NUMBER OF WORDS IN THIS DESCRIPTOR
		    JRST LOAD7]	;  UPDATE CORE ADDRESS AND DO NEXT ONE
	CAMGE	P4,BLKNUM	;PAGE NUMBERS IN THE EXE DIRECTORY MUST
	JRST	BDFERR		;  BE MONOTONICALLY INCREASING
LOAD2:	PUSHJ	P,POSFIL	;POSITION FILE TO THAT BLOCK
	  POPJ	P,		;HIT EOF
LOAD3:	SKIPGE	0(P1)		;THIS A HIGH SEG PAGE?
	JRST	LOAD5		;YES, READ IN JUST AFTER LOW SEG
	HRRZ	P3,1(P1)	;GET CORE PAGE NUMBER
	LSH	P3,P2WLSH	;COMPUTE CORE ADDRESS
	JUMPN	P3,LOAD5	;GO IF NOT ZERO
	HRL	P4,P2		;REMEMBER NUMBER OF BLOCKS
	MOVEI	P2,PAGSIZ/BLKSIZ ;  AND READ ONE PAGE
LOAD4:	MOVEI	P3,PAGSIZ	;  STARTING AT 1000
LOAD5:	PUSHJ	P,REDBLK	;READ THE SPECIFIED BLOCKS
	  POPJ	P,		;FAILED
	HLRZ	P2,P4		;WERE WE READING 0-777
	JUMPE	P2,LOAD7	;  INTO 1000-1777?
	TRNN	S,FR.RBT	;DOING A REBOOT?
	JRST	LOAD6		;NO, CONTINUE
	SKIPN	T2,.VPAG0+PAGSIZ+MBTCOM ;GET PAGE NUMBER OF COMM AREA
	JRST	NSSERR		;NOT A REBOOTABLE CRASH
	TLZ	T2,-1		;CLEAR JUNK
	PUSHJ	P,MOVBTS	;MOVE US TO THOSE PAGES
	SKIPA	T1,[.VPAG0+PAGSIZ,,.VPAG0] ;SETUP TO BLT ENTIRE PAGE
LOAD6:	MOVE	T1,[.VPAG0+PAGSIZ+40,,.VPAG0+40] ;SETUP TO BLT 40-777
	BLT	T1,.VPAG0+PAGSIZ-1 ;MOVE THEM TO WHERE THEY BELONG
	HRRZS	P4		;CLEAR FLAG
	SUBI	P2,PAGSIZ/BLKSIZ ;COMPENSATE FOR WHAT WE READ
	JUMPG	P2,LOAD4	;DO THE REST IF MORE
LOAD7:	AOBJN	P1,.+1		;SKIP PAST FIRST OF 2 WORDS
	AOBJN	P1,LOAD1	;AND DO NEXT DESCRIPTOR
	JRST	CPOPJ1		;GIVE SKIP RETURN
	SUBTTL	FILE SEARCH SUBROUTINES ;⊗ FNDMON


;ROUTINE TO FIND THE FILE CONTAINING THE MONITOR SPECIFIED IN THE
;FILESPEC AREA, READ THE EXE DIRECTORY INTO BUF AND SETUP TO READ
;THE FILE.
;CALL:	PUSHJ	P,FNDMON
;RETURN+1 IF FAILED WITH ERROR CODE IN T1
;RETURN+2 IF SUCCESSFUL WITH
;	  P1/AOBJN POINTER TO EXE DIRECTORY DESCRIPTORS
;DESTROYS P3-P4

FNDMON:	PUSHJ	P,FNDFIL	;FIND THE FILE
	  POPJ	P,		;FILE NOT FOUND
	PUSHJ	P,REDBUF	;READ 1ST BLOCK OF EXE DIRECTORY
	  POPJ	P,		;FAILED
	HLRZ	T1,BUF		;GET CODE
	HRRZ	P1,BUF		;AND LENGTH OF DIRECTORY
	CAIN	T1,SV.DIR	;THIS AN EXE FILE?
	CAILE	P1,BLKSIZ-1	;AND NOT TOO LONG?
	JRST	BDFERR		;NO, BAD DIRECTORY FORMAT
	MOVNI	P1,-1(P1)	;BUILD -VE COUNT FOR AOBJN POINTER
	HRLI	P1,BUF+1	;AND FIRST WORD
	MOVSS	P1		;MAKE IT AN AOBJN POINTER TO BUF
	JRST	CPOPJ1		;GIVE SKIP RETURN
;ROUTINE TO FIND A FILE AND SETUP ITS RIB IN RIB.  CALL WITH ;⊗ FNDFIL FNDFI1 FNDFI2
;FILESPEC AREA SETUP.
;CALL:	PUSHJ	P,FNDFIL
;RETURN+1 IF NOT FOUND OR READ ERROR ON DIRECTORY WITH CODE IN T1
;RETURN+2 IF FILE FOUND
;DESTROYS P3-P4

FNDFIL:	TLZ	S,(FL.FFL)	;HAVEN'T FOUND FILE YET
	PUSHJ	P,SAVE2		;SAVE P1-P2
	PUSHJ	P,FNDMFD	;FIND THE MFD
	  JRST	SNTERR		;FAILED
	MOVEI	P1,0		;SETUP LOOP POINTER TO PTHBLK
FNDFI1:	SKIPN	P3,PTHBLK(P1)	;GET NEXT UFD/SFD FROM PATH BLOCK
	MOVE	P3,FILNAM	;FOUND END, USE FILENAME
	MOVEI	P4,'UFD'	;ASSUME EXTENSION IS UFD
	JUMPE	P1,FNDFI2	;GO IF CORRECT
	MOVEI	P4,'SFD'	;ASSUME SFD
	SKIPN	PTHBLK(P1)	;DONE WITH PATH BLOCK?
	HLRZ	P4,EXT		;YES, USE REAL EXTENSION
FNDFI2:	PUSHJ	P,SRCHFD	;SEARCH THE DIRECTORY
	  JRST	FNTERR		;FILE NOT FOUND
	PUSH	P,T2		;SAVE BLOCK IN UNIT OF RIB
	PUSHJ	P,FNDLUN	;FIND SPECIFIED UNIT
	  JRST	[POP	P,(P)	;FLUSH STACK
		 JRST	SNTERR]	;GIVE ERROR CODE AND RETURN
	POP	P,F		;RESTORE BLOCK OF RIB
	PUSHJ	P,REDRBP	;READ THE RIB OF THE FILE
	  JRST	FNTERR		;FAILED
	SKIPE	PTHBLK(P1)	;FOUND UFD, ALL SFD'S AND FILE?
	AOJA	P1,FNDFI1	;NO, TRY NEXT LEVEL
	TLO	S,(FL.FFL)	;INDICATE THAT WE FOUND THE FILE
	JRST	CPOPJ1		;GIVE SKIP RETURN, RIB SETUP
;ROUTINE TO FIND THE MFD FOR A STRUCTURE.  CALL WITH DEV CONTAINING ;⊗ FNDMFD FNDMF1 SRCHFD SRCHF1 SRCHF2
;THE STRUCTURE NAME.
;CALL:	PUSHJ	P,FNDMFD
;RETURN+1 IF FAILED
;RETURN+2 IF FOUND WITH MFD RIB IN RIB
;DESTOYS P3-P4

FNDMFD:	SETZM	LUNPOS		;FIND UNIT ZERO OF STRUCTURE
	PUSHJ	P,FNDUNI	;FIND IT
	  POPJ	P,		;FAILED, GIVE UP
	MOVE	T1,HOM+HOMMFD	;GET BLOCK IN STR CONTAINING MFD RIB
	MOVE	T2,HOM+HOMBSC	;GET BLOCKS/SUPERCLUSTER
	IMUL	T2,HOM+HOMSCU	;TIME SUPERCLUSTERS/UNIT
	IDIV	T1,T2		;T1=UNIT, T2=BLOCK IN UNIT OF RIB
	PUSH	P,T2		;SAVE BLOCK NUMBER
	JUMPE	T1,FNDMF1	;GO IF ON UNIT ZERO
	MOVEM	T1,LUNPOS	;STORE UNIT
	PUSHJ	P,FNDUNI	;FIND UNIT
	  JRST	TPOPJ		;FAILED
FNDMF1:	POP	P,F		;RESTORE BLOCK IN UNIT
	MOVE	P3,[1,,1]	;FILENAME IS [1,,1]
	MOVEI	P4,'UFD'	;EXTENSION IS UFD
	PJRST	REDRBP		;READ RIB OF MFD AND RETURN


;ROUTINE TO SEARCH A UFD OR SFD FOR A FILE.  CALL WITH RIB SETUP
;IN RIB.
;CALL:
;	P3/FILENAME,	P4/0,,EXTENSION
;	PUSHJ	P,SRCHFD
;RETURN+1 IF FILE NOT FOUND
;RETURN+2 IF FOUND
;RETURNS T1=UNIT IN STR, T2=BLOCK IN UNIT OF RIB FOR FILE.

SRCHFD:	PUSHJ	P,REDBUF	;READ THE NEXT BLOCK OF THE DIRECTORY
	  POPJ	P,		;EOF OR READ ERROR
	MOVSI	T1,-BLKSIZ	;BUILD AOBJN POINTER TO BLOCK
SRCHF1:	HLRZ	T2,BUF+1(T1)	;GET EXTENSION
	CAMN	P3,BUF(T1)	;FILENAMES MATCH?
	CAME	P4,T2		;YES, EXTENSIONS MATCH?
	AOBJN	T1,.+2		;NO, INCREMENT PAST FILENAME
	JRST	SRCHF2		;YES
	AOBJN	T1,SRCHF1	;LOOP FOR ALL OF THIS BLOCK
	JRST	SRCHFD		;TRY NEXT BLOCK
SRCHF2:	HRRZ	T1,BUF+1(T1)	;GET CFP FROM DIRECTORY
	IDIV	T1,HOM+HOMSCU	;T1=UNIT, T2=SUPERCLUSTER IN UNIT
	IMUL	T2,HOM+HOMBSC	;T2=BLOCK IN UNIT
	JRST	CPOPJ1		;GIVE SKIP RETURN
	SUBTTL	BLOCK READ/WRITE SUBROUTINES ;⊗ WRTRIB WRTBUF REDBUF


;ROUTINE TO WRITE BUF/RIB TO THE OUTPUT FILE.  CALL WITH RIB OF FILE
;SETUP.
;CALL:	PUSHJ	P,WRTBUF  -OR-  PUSHJ P,WRTRIB
;RETURN+1 IF ERROR DETECTED WITH ERROR CODE IN T1
;RETURN+2 IF SUCCESSFUL

WRTRIB:	MOVEI	R,RIB		;POINT TO RIB
	AOS	SAVSIZ		;COMPENSATE FOR SELBLK DECREMENTING SAVSIZ
	TLZA	S,(FL.RIB)	;FORCE SELBLK TO WRITE THE RIB
WRTBUF:	MOVEI	R,BUF		;POINT TO BUF
	MOVEI	T1,1		;NUMBER OF BLOCKS IS 1
	PUSHJ	P,SELBLK	;SETUP TO DO THAT MANY
	  JRST	EOFERR		;FILE MUST BE REALLY SCREWED UP
	JUMPN	T1,EOFERR	;DITTO
	PUSHJ	P,VRTWRT	;WRITE THE BLOCK
	  JRST	IOFERR		;WRITE ERROR
	JRST	CPOPJ1		;GIVE SKIP RETURN


;ROUTINE TO READ ONE BLOCK FROM THE INPUT FILE INTO BUF.  CALL WITH
;RIB OF FILE SETUP.
;CALL:	PUSHJ	P,REDBUF
;RETURN+1 IF ERROR DETECTED WITH ERROR CODE IN T1
;RETURN+2 IF SUCCESSFUL

REDBUF:	MOVEI	R,BUF		;POINT TO BUF
	MOVEI	T1,1		;NUMBER OF BLOCKS IS 1
	PUSHJ	P,SELBLK	;SETUP TO READ
	  JRST	EOFERR		;HIT EOF
	JUMPN	T1,EOFERR	;DITTO
	PUSHJ	P,VRTRED	;READ THE BLOCK
	  JRST	IOFERR		;READ ERROR
	JRST	CPOPJ1		;GIVE SKIP RETURN
;ROUTINE TO POSITION AN EXE FILE SO THAT THE NEXT READ WILL READ ;⊗ POSFIL REDBLK
;THE BLOCKS THAT WE WANT.
;CALL:
;	P4/DESIRED BLOCK IN FILE
;	PUSHJ	P,POSFIL
;RETURN+1 IF EOF ENCOUNTERED WITH ERROR CODE IN T1
;RETURN+2 WITH FILE POSITIONED CORRECTLY

POSFIL:	CAMN	P4,BLKNUM	;AT THE RIGHT BLOCK IN THE FILE NOW?
	JRST	CPOPJ1		;YES, GIVE SKIP RETURN
	MOVEI	T1,1		;DO ONE BLOCK
	PUSHJ	P,SELBLK	;USETI .+1
	  JRST	EOFERR		;CANNOT HAVE EOF HERE
	JRST	POSFIL		;TRY AGAIN


;ROUTINE TO READ ONE OR MORE BLOCKS FROM AN EXE FILE.
;CALL:	P2/NUMBER OF BLOCKS TO READ
;	P3/CORE ADDRESS OF WHERE TO READ FIRST BLOCK
;	P4/FILE BLOCK NUMBER OF FIRST BLOCK
;	PUSHJ	P,REDBLK
;RETURN+1 IF ERROR WITH ERROR CODE IN T1
;RETURN+2 IF SUCCESSFUL WITH P3 AND P4 UPDATED TO REFLECT THE TRANSFER

REDBLK:	JUMPLE	P2,CPOPJ1	;READ ALL BLOCKS YET?
	MOVE	T1,P2		;NO, GET NUMBER OF BLOCKS TO TRANSFER
	PUSHJ	P,SELBLK	;SETUP TO DO THAT MANY
	  JRST	EOFERR		;CAN'T HAVE EOF
	MOVE	R,P3		;PUT CORE ADDRESS IN R
	MOVE	P2,T1		;COPY BLOCKS WE COULDN'T DO FOR NEXT TIME
	ADD	P4,M		;INCREMENT FILE BLOCK NUMBER
	MOVE	T1,M		;GET NUMBER OF BLOCKS TO DO
	LSH	T1,B2WLSH	;CONVERT TO WORDS
	ADD	P3,T1		;UPDATE CORE ADDRESS
	PUSHJ	P,@REDTAB(W)	;READ THE SPECIFIED BLOCKS
	  JRST	IOFERR		;I/O ERROR
	JRST	REDBLK		;CONTINUE FOR ALL
;ROUTINE TO FIND A UNIT AND READ IT'S HOM BLOCK. CALL WITH LUNPOS ;⊗ FNDLUN FNDUNI FNDUN1 FNDUN2 FNDUN3
;CONTAINING THE LOGICAL UNIT NUMBER AND DEV CONTAINING THE DEVICE
;NAME.
;CALL:
;	T1/LOGICAL UNIT IN STRUCTURE
;	PUSHJ	P,FNDLUN
;RETURN+1 IF NOT FOUND
;RETURN+2 IF FOUND WITH HOM BLOCK IN HOM

FNDLUN:	EXCH	T1,LUNPOS	;STORE UNIT, GET CURRENT
	CAMN	T1,LUNPOS	;SAME AS CURRENT ONE?
	JRST	CPOPJ1		;YES, ALREADY THERE
;;	PJRST	FNDUNI		;FALL INTO FNDUNI


;ROUTINE TO FIND A UNIT BY EXHAUSTIVE SEARCH.  CALL WITH LUNPOS
;CONTAINING THE LOGICAL UNIT NUMBER IN THE STRUCTURE, DEV CONTAINING
;THE STRUCTURE NAME AND SDLPOS CONTAINING THE POSITION IN THE SYSTEM
;DUMP LIST.
;CALL:	PUSHJ	P,FNDUNI
;RETURN+1 IF NOT FOUND
;RETURN+2 IF FOUND WITH HOM BLOCK IN HOM

FNDUNI:	MOVSI	J,-DVCTBL	;AOBJN POINTER TO DEVICE CODE TABLE
FNDUN1:	MOVSI	U,-MAXUNI	;AOBJN POINTER FOR EACH UNIT
FNDUN2:	HLRZ	W,DVCTAB(J)	;SETUP TYPE OFFSET
	PUSHJ	P,SETIOT	;SETUP I/O INSTRUCTIONS
	PUSHJ	P,REDHOM	;READ HOM BLOCK FOR UNIT
	  JRST	FNDUN3		;FAILED OR BAD
	MOVE	T1,HOM+HOMLUN	;GET LOGICAL UNIT NUMBER OF THIS STR
	MOVE	T2,HOM+HOMSNM	;GET STR NAME
	CAMN	T1,LUNPOS	;UNIT NUMBER MATCH?
	CAME	T2,DEV		;YES, DOES IT?
	JRST	FNDUN3		;NO
	JRST	CPOPJ1		;YES, GIVE SKIP RETURN
FNDUN3:	AOBJN	U,FNDUN2	;LOOP FOR NEXT UNIT
	AOBJN	J,FNDUN1	;LOOP FOR NEXT CONTROLLER
	POPJ	P,		;ERROR RETURN
;ROUTINE TO READ A HOM BLOCK. ;⊗ REDHOM REDHO1 REDHO2
;CALL:
;	U/PHYSICAL UNIT NUMBER
;	J/OFFSET INTO DEVICE CODE TABLE
;	W/OFFSET INTO TYPE TABLES
;	PUSHJ	P,REDHOM
;RETURN+1 IF ERROR
;RETURN+2 IF SUCCESSFUL WITH HOM BLOCK IN HOM

REDHOM:	MOVEI	R,HOM		;ADDRESS OF WHERE TO PUT IT
	MOVEI	F,LBNHOM	;ADDRESS OF FIRST HOM BLOCK ON UNIT
	MOVEI	M,1		;READ 1 BLOCK
REDHO1:	PUSHJ	P,VRTRED	;READ THE BLOCK
	  JRST	REDHO2		;FAILED, TRY SECOND
	MOVS	T1,HOM+HOMNAM	;GET FIRST WORD OF BLOCK
	MOVE	T2,HOM+HOMCOD	;GET WORD CONTAINING UNLIKELY CODE
	CAIN	T1,'HOM'	;NAME MUST BE HOM
	CAIE	T2,CODHOM	;AND MUST MATCH UNLIKELY CODE
	JRST	REDHO2		;ONE FAILED
	CAMN	F,HOM+HOMSLF	;SELF POINTER MUST MATCH
	SKIPE	HOM+HOMREF	;AND MUST NOT NEED REFRESHING
	JRST	REDHO2		;FAILED
	MOVEI	T1,T4		;SETUP HOMCLP AND
	HRRM	T1,HOM+HOMCLP	;  HOMCNP TO POINT
	HRRM	T1,HOM+HOMCNP	;  TO T4
	JRST	CPOPJ1		;GIVE SKIP RETURN
REDHO2:	CAIN	F,LBNHOM	;DOING FIRST HOM BLOCK?
	POPJ	P,		;NO, GIVE FAIL RETURN
	MOVEI	F,LB2HOM	;GET ADDRESS OF 2ND
	JRST	REDHO1		;AND TRY THAT ONE
;ROUTINE TO READ A RIB. ;⊗ REDRIB REDRBP
;CALL:
;	U/PHYSICAL UNIT NUMBER
;	J/OFFSET INTO DEVICE CODE TABLE
;	W/OFFSET INTO TYPE TABLES
;	F/BLOCK IN UNIT
;	PUSHJ	P,REDRIB
;RETURN+1 IF READ OR RIB ERROR
;RETURN+2 IF SUCCESSFUL WITH RIB IN RIB
;CALL REDRBP IF FILENAME AND EXTENSION ALREADY IN P3,P4
;DESTROYS P3-P4

REDRIB:	MOVE	P3,FILNAM	;GET FILENAME
	HLRZ	P4,EXT		;AND EXT
REDRBP:	MOVEI	R,RIB		;ADDRESS OF WHERE TO READ IT
	MOVEI	M,1		;READ 1 BLOCK
	PUSHJ	P,VRTRED	;READ THE BLOCK
	  POPJ	P,		;FAILED
	MOVE	T1,RIB+RIBCOD	;GET WORD CONTAINING UNLIKELY CODE
	CAIN	T1,CODRIB	;MUST MATCH
	SKIPL	T1,RIB+RIBFIR	;POINTER MUST BE NEGATIVE
	POPJ	P,		;FAILED
	MOVEM	T1,SAVFIR	;SAVE FOR SELBLK
	MOVE	T1,RIB+RIBNAM	;GET FILENAME FROM RIB
	CAMN	T1,P3		;MATCH WITH WHAT WE WANT?
	CAME	F,RIB+RIBSLF	;SELF POINTER MUST MATCH
	POPJ	P,		;ELSE ERROR
	HLRZ	T1,RIB+RIBEXT	;GET EXTENSION FROM RIB
	MOVE	T2,PTHBLK	;GET PPN FROM PATH BLOCK
	CAIN	P4,'UFD'	;READING A UFD?
	MOVE	T2,[1,,1]	;YES, PPN IS 1,1
	CAMN	T1,P4		;EXTENSION MATCH?
	CAME	T2,RIB+RIBPPN	;  ALONG WITH PPN?
	POPJ	P,		;NO, ERROR
	TLO	S,(FL.RIB)	;TELL SELBLK THAT FIRST BLOCK IS A RIB
	SETOM	BLKCNT		;AND NO BLOCKS LEFT IN GROUP
	MOVE	T1,RIB+RIBSIZ	;GET RIBSIZ FROM RIB
	ADDI	T1,BLKSIZ-1	;ROUND UP TO A BLOCK
	LSH	T1,W2BLSH	;CONVERT TO BLOCKS
	TLZE	S,(FL.EXR)	;READING EXTENDED RIB?
	JRST	CPOPJ1		;YES, GIVE SKIP RETURN
	MOVEM	T1,SAVSIZ	;NO, SAVE SIZE FOR SELBLK
	SETZM	BLKNUM		;AND ZERO RELATIVE BLOCK IN FILE
	JRST	CPOPJ1		;AND GIVE SKIP RETURN
;ROUTINE TO SETUP A TRANSFER TO/FROM DISK. ;⊗ SELBLK SELBL1 SELBL2 SELBL3
;CALL:
;	T1/NUMBER OF BLOCKS DESIRED TO TRANSFER
;	PUSHJ	P,SELBLK
;RETURN+1 IF EOF DETECTED
;RETURN+2 IF SOME TRANSFER IS POSSIBLE
;RETURNS M/NUMBER OF BLOCKS POSSIBLE, T1/NUMBER OF BLOCKS IN REQUEST
;	 THAT COULDN'T BE TRANSFERED, F/BLOCK ON UNIT OF FIRST BLOCK.
;PRESERVES P3-P4

SELBLK:	TLNN	S,(FL.RIB)	;WANT TO SKIP FIRST RIB BLOCK?
	JRST	SELBL1		;NO
	PUSHJ	P,SAVE2		;SAVE P1-P2
	MOVE	P1,T1		;SAVE REQUESTED TRANSFER IN P1
	MOVEI	T1,1		;AND MAKE IT LOOK LIKE 1 BLOCK
SELBL1:	SKIPLE	BLKCNT		;AND MORE BLOCKS LEFT IN GROUP?
	JRST	SELBL4		;YES, USE THEM
SELBL2:	SKIPL	T2,SAVFIR	;RUN OUT OF POINTERS?
	JRST	SELBL5		;YES, CHECK FOR EXTENDED RIBS
	MOVE	T4,RIB(T2)	;GET NEXT POINTER
	AOBJN	T2,.+1		;INCREMENT POINTER TO POINTERS
	MOVEM	T2,SAVFIR	;STORE POINTER BACK
	LDB	T2,HOM+HOMCNP	;GET CLUSTER COUNT FROM THIS POINTER
	JUMPN	T2,SELBL3	;GO IF NON-ZERO
	TRZN	T4,RIPNUB	;UNIT CHANGE POINTER?
	POPJ	P,		;NO, THAT'S AN EOF POINTER
	PUSH	P,T1		;SAVE ARGUMENT
	MOVE	T1,T4		;COPY NEW UNIT NUMBER
	PUSHJ	P,FNDLUN	;FIND IT AND SETUP HOM BLOCK
	  JRST	TPOPJ		;NOT THERE, SIMULATE EOF
	POP	P,T1		;RESTORE ARGUMENT
	JRST	SELBL2		;TRY WITH NEXT POINTER
SELBL3:	IMUL	T2,HOM+HOMBPC	;COMPUTE NUMBER OF BLOCKS IN GROUP
	SKIPL	SAVFIR		;DOING LAST POINTER IN THIS RIB?
	SUBI	T2,1		;YES, DON'T OVERWRITE SPARE RIB
	TLNE	S,(FL.RIB)	;SKIPPING A RIB?
	AOS	SAVSIZ		;YES, FILE IS 1 MORE BLOCK LONG
	CAMLE	T2,SAVSIZ	;MORE THAN AMOUNT REMAINING IN FILE?
	MOVE	T2,SAVSIZ	;YES, USE THAT
	MOVEM	T2,BLKCNT	;STORE IT
	LDB	T2,HOM+HOMCLP	;GET CLUSTER ADDRESS OF 1ST CLUSTER IN GROUP
	IMUL	T2,HOM+HOMBPC	;COMPUTE BLOCK ADDRESS
	MOVEM	T2,BLKADR	;STORE ADDRESS OF BLOCK


				;CONTINUED ON THE NEXT PAGE
SELBL4:	MOVN	M,T1		;GET -VE NUMBER OF BLOCKS IN REQUEST ;⊗ SELBL4 SELBL5 SELBL6
	SUB	T1,BLKCNT	;SUBTRACT AMOUNT LEFT IN GROUP
	SKIPLE	T1		;REQUEST LARGER THAN AMOUNT WE HAVE?
	MOVN	M,BLKCNT	;YES, USE WHAT WE HAVE
	ADDM	M,BLKCNT	;DECREASE BLKCNT BY APPROPRIATE AMOUNT
	ADDM	M,SAVSIZ	; AND SIZE OF FILE
	MOVNS	M		;SET M TO AMOUNT TO TRANSFER
	MOVE	F,BLKADR	;START AT THIS BLOCK
	ADDM	M,BLKADR	;INCREMENT BLOCK ADDRESS FOR NEXT CALL
	TLNN	S,(FL.RIB)	;SKIPING A RIB?
	ADDM	M,BLKNUM	;NO, UPDATE RELATIVE FILE BLOCK
	SKIPGE	T1		;CAN WE DO THE WHOLE REQUEST?
	MOVEI	T1,0		;YES, RETURN ZERO AS REMAINDER
	TLZN	S,(FL.RIB)	;SKIPPING 1 BLOCK FOR RIB?
	JRST	CPOPJ1		;NO, RETURN TO CALLER
	MOVE	T1,P1		;RESTORE ORIGINAL REQUEST
	JRST	SELBL1		;AND DO THE REAL REQUEST
SELBL5:	SKIPN	RIB+RIBXRA	;EXTENDED RIB POINTER?
	POPJ	P,		;NO, GIVE EOF RETURN
	PUSH	P,T1		;SAVE ARGUMENT
	PUSH	P,P3		;AND QUASI-PRESERVED REGISTERS
	PUSH	P,P4		;SMASHED BY REDRIB
	LDB	T1,DEYRBU	;GET UNIT ON WHICH NEXT RIB EXISTS
	PUSHJ	P,FNDLUN	;FIND UNIT, SETUP HOM BLOCK
	  JRST	SELBL6		;FAILED GIVE EOF RETURN
	LDB	F,DEYRBA	;GET CLUSTER ADDRESS ON THAT UNIT
	IMUL	F,HOM+HOMBPC	;CONVERT TO BLOCK ADDRESS
	TLO	S,(FL.EXR)	;DON'T CHANGE SAVSIZ FOR EXTENDED RIBS
	PUSHJ	P,REDRIB	;READ NEW RIB
	  JRST	SELBL6		;FAILED, GIVE EOF RETURN
	POP	P,P4		;RESTORE P4 AND
	POP	P,P3		;  P3
	POP	P,T1		;RESTORE ARGUMENT
	JRST	SELBLK		;AND TRY NEW POINTER FROM THIS RIB
SELBL6:	TLZ	S,(FL.EXR)	;MAKE SURE THIS FLAG IS OFF
IFN FTKL10!FTKS10,<
	ADJSP	P,-3		;BRING STACK INTO SYNC
>
IFN FTKI10,<
	SUB	P,[3,,3]	;HARDER FOR THE KI10
>
	POPJ	P,		;AND GIVE NON-SKIP RETURN
	SUBTTL	SUPPORT SUBROUTINES ;⊗ CLRBUF SETIOT ERRTAB SNTERR FNTERR UPDERR EOFERR IOFERR BDFERR MCCERR NSSERR ERRTBL ALLERR


;ROUTINE TO CLEAR BUF.
;CALL:	PUSHJ	P,CLRBUF	
;RETURN+1 ALWAYS

CLRBUF:	SETZM	BUF		;CLEAR FIRST WORD
	MOVE	T1,[BUF,,BUF+1]	;SETUP FOR BLT
	BLT	T1,BUF+BLKSIZ-1 ;CLEAR IT ALL
	POPJ	P,		;RETURN


;ROUTINE TO STORE A DEVICE CODE IN ALL I/O INSTRUCTIONS.
;CALL:
;	J/OFFSET INTO DEVICE CODE TABLE
;	PUSHJ	P,SETIOT
;RETURN+1 ALWAYS

SETIOT:
IFN FTKL10!FTKI10,<
	HRRZ	T1,DVCTAB(J)	;GET DEVICE CODE
	MOVSI	T2,-IOTTBL	;BUILD AOBJN POINTER TO IOTTAB
	DPB	T1,[POINT 7,IOTTAB(T2),9] ;STORE DEVICE CODE IN INSTN.
	AOBJN	T2,.-1		;DO THEM ALL
>
	POPJ	P,		;RETURN


;RETURN POINTS TO SET T1 TO AN ERROR CODE AND NON-SKIP RETURN

ERRTAB:
SNTERR:	PJSP	T1,ALLERR	;STRUCTURE NOT FOUND
FNTERR:	PJSP	T1,ALLERR	;FILE NOT FOUND
UPDERR:	PJSP	T1,ALLERR	;UNPROCESSED DUMP
EOFERR:	PJSP	T1,ALLERR	;UNEXPECTED EOF
IOFERR:	PJSP	T1,ALLERR	;I/O ERROR
BDFERR:	PJSP	T1,ALLERR	;BAD DIRECTORY FORMAT
MCCERR:	PJSP	T1,ALLERR	;MEM CONFIG TOO COMPLICATED
NSSERR:	PJSP	T1,ALLERR	;NOT SYSTEM SLEEP DUMP
ERRTBL==.-ERRTAB
ALLERR:	SUBI	T1,ERRTAB+1	;COMPUTE ERROR CODE
	TLZ	T1,-1		;CLEAR LH JUNK
	POPJ	P,		;RETURN
;ROUTINE TO READ DATA INTO A VIRTUAL ADDRESS. ;⊗ VRTRED VRTWRT MAPADR
;CALL:
;	R/VIRTUAL ADDRESS
;	M/NUMBER OF BLOCKS TO TRANSFER
;	F/BLOCK ON UNIT
;	U/PHYSICAL UNIT
;	W/OFFSET INTO TYPE TABLE
;	J/OFFSET INTO DEVICE CODE TABLE
;	PUSHJ	P,VRTRED
;RETURN+1 IF ERROR
;RETURN+2 IF SUCCESSFUL

VRTRED:	PUSHJ	P,MAPADR	;CONVERT VIRTUAL TO PHYSICAL ADDRESS
	PJRST	@REDTAB(W)	;DO THE TRANSFER


;ROUTINE TO WRITE DATA FROM A VIRTUAL ADDRESS.  CALL WITH SAME ARGUMENTS
;AS VRTRED.
;CALL:	PUSHJ	P,VRTWRT
;RETURN+1 IF ERROR
;RETURN+2 IF SUCCESSFUL

VRTWRT:	PUSHJ	P,MAPADR	;CONVERT VIRTUAL TO PHYSICAL ADDRESS
	PJRST	@WRTTAB(W)	;DO THE TRANSFER


;ROUTINE TO CONVERT A VIRTUAL ADDRESS TO A PHYSICAL ADDRESS.
;CALL:
;	R/VIRTUAL ADDRESS
;	PUSHJ	P,MAPADR
;RETURN+1 ALWAYS WITH PHYSICAL ADDRESS IN R

MAPADR:
IFN FTKI10,<
	PUSH	P,R		;SAVE VIRTUAL ADDRESS
	ANDI	R,PAGSIZ-1	;KEEP ONLY OFFSET IN PAGE
	EXCH	R,0(P)		;STORE THAT, GET FULL ADDRESS
>
	MAP	R,(R)		;CONVERT TO PHYSICAL ADDRESS
IFN FTKI10,<
	LSH	R,P2WLSH	;CONVERT PAGE NUMBER TO ADDRESS
	IOR	R,0(P)		;INCLUDE OFFSET IN PAGE
	POP	P,(P)		;FLUSH STACK
	TLZ	R,(↑-<PG.EPT*PAGSIZ+PAGSIZ-1>) ;KEEP ONLY ADDRESS
>
IFN FTKL10,<
	TLZ	R,(↑-<LG.EPT*PAGSIZ+PAGSIZ-1>) ;KEEP ONLY ADDRESS
>
IFN FTKS10,<
	TLZ	R,(↑-<SG.EPT*PAGSIZ+PAGSIZ-1>) ;KEEP ONLY ADDRESS
>
	POPJ	P,		;AND RETURN
;ROUTINE TO SAVE P1 AND P2 AND CALL THE CALLER AS A COROUTINE ;⊗ SAVE2 SAVFR
;WHICH RESTORES P1 AND P2 WHEN THE CALLER RETURNS.
;CALL:	PUSHJ	P,SAVE2
;RETURN+1 ALWAYS

SAVE2:	EXCH	P1,(P)		;GET RETURN, SAVE P1
	PUSH	P,P2		;SAVE P2
	MOVEM	P1,1(P)		;SAVE RETURN
	MOVE	P1,-1(P)	;RESTORE P1
	PUSHJ	P,@1(P)		;CALL CALLER
	  CAIA			;NON SKIP
	AOS	-2(P)		;SKIP RET
	POP	P,P2		;RESTORE P2
	POP	P,P1		;RESTORE P1
	POPJ	P,		;RETURN


;ROUTINE TO SAVE F AND R AND CALL THE CALLER AS A COROUTINE
;WHICH RESTORES F AND R WHEN THE CALLER RETURNS.
;CALL:	PUSHJ	P,SAVFR
;RETURN+1 ALWAYS
SAVFR:	EXCH	F,(P)		;GET RETURN, SAVE F
	PUSH	P,R		;SAVE R
	MOVEM	F,1(P)		;SAVE RETURN
	MOVE	F,-1(P)		;RESTORE F
	PUSHJ	P,@1(P)		;CALL CALLER
	  CAIA			;NON SKIP
	AOS	-2(P)		;SKIP RET
	POP	P,R		;RESTORE R
	POP	P,F		;RESTORE F
	POPJ	P,		;RETURN
	SUBTTL	MOVE BOOT TO TOP OF MEMORY AND ZERO CORE ;⊗ MOVBTS


;ROUTINE TO MOVE BOOT TO THE TOP OF CORE SO THAT A NEW MONITOR
;CAN BE LOADED.  ALSO CALLED ON A REBOOT REQUEST TO MOVE BOOT TO THE
;COMMUNICATION REGION SPECIFIED BY MBTCOM IN THE DUMP.
;CALL:
;	T2/PHYSICAL PAGE NUMBER OF WHERE TO MOVE BOOT
;	PUSHJ	P,MOVBTS
;RETURN+1 ALWAYS

MOVBTS:	LSH	T2,P2WLSH	;CONVERT PAGE NUMBER TO ADDRESS
	CAMN	T2,EPTADR	;MOVING TO THE SAME SPOT?
	POPJ	P,		;YES, JUST RETURN
	MOVEM	T2,EPTADR	;STORE PHYSICAL ADDRESS OF NEW EPT
	LSH	T2,W2PLSH	;CONVERT BACK TO PAGE NUMBER
	MOVEI	T1,PM.ACC+PM.WRT(T2) ;GET MAP SLOT ENTRY FOR THIS PAGE
	HRLI	T1,-BOOPGS	;MAKE IT AN AOBJN POINTER
	MOVE	T3,[POINT 18,EPT+.MMOVE] ;GET BYTE POINTER TO MAP SLOT
	IDPB	T1,T3		;MAKE ENOUGH PAGE ADDRESSABLE TO MOVE BOOT
	AOBJN	T1,.-1		;DO THEM ALL
	MOVE	T1,CPEBR	;GET CURRENT MAPPING
	XCT	CHGEBR		;CAUSE THE PAGE TABLE TO BE FLUSHED
	MOVE	T3,[.VBOOT,,.VMOVE] ;SETUP BLT WORD TO MOVE IT ALL
	BLT	T3,.VMOVE+BOOLEN-1 ;DO SO
	MOVEI	T3,PM.ACC+PM.WRT(T2) ;GET MAP SLOT ENTRY
	HRLI	T3,-BOOPGS	;MAKE ANOTHER AOBJN POINTER
	MOVE	T4,[POINT 18,.VMOVE+.MBOOT] ;POINT TO MAP
	IDPB	T3,T4		;SLOTS IN NEW MAP TO MAKE US
	AOBJN	T3,.-1		;ADDRESSABLE
IFN FTKI10,<
	TRZ	T1,PG.EPT	;CLEAR OLD PAGE NUMBER
	MOVSI	T4,<(PG.LUB)>(T2) ;GET ARGUMENT TO CHANGE UBR ALSO
>
IFN FTKL10,<
	TRZ	T1,LG.EPT	;CLEAR OLD PAGE NUMBER
	MOVEI	T4,LG.IAM(T2)	;GET ARGUMENT TO CHANGE
	HRLI	T4,(LG.LAB!LG.LPC!LG.LUB)  ; UBR ALSO
>
IFN FTKS10,<
	TRZ	T1,SG.EPT	;CLEAR OLD PAGE NUMBER
	MOVEI	T4,(T2)		;GET ARGUMENT TO CHANGE
	HRLI	T4,(SG.LAB!SG.LUB)  ; UBR ALSO
>
	IORI	T1,(T2)		;INSERT NEW EPT PAGE NUMBER
	MOVEM	T1,.VMOVE+CPEBR-.VBOOT ;STORE NEW MAPPING
	XCT	CHGEBR		;CONTINUE EXECUTION AT TOP OF CORE
	XCT	CHGUBR		;CHANGE UPT ALSO
;HERE AFTER HAVING MOVED BOOT TO THE TOP OF CORE TO ZERO ALL OTHER ;⊗ MOVBT1 MOVBT2
;PAGES IN MEMORY.  ONLY DO THIS ONCE.

	TLOE	S,(FL.ZER)	;ALREADY DONE THIS ONCE?
	POPJ	P,		;YES, RETURN NOW
	MOVE	T4,T2		;PUT EPT PAGE NUMBER IN T4
	MOVE	T2,MEMPSZ	;GET NUMBER OF PAGES DESCRIBED BY NXMTAB
	SUBI	T2,1		;CALCULATE THE HIGHEST PAGE # IN CORE
MOVBT1:	CAIL	T2,(T4)		;IS THIS PAGE
	CAILE	T2,BOOPGS-1(T4)	;  OCCUPIED BY BOOT?
	PUSHJ	P,CHKNXM	;NO, DOES IT EXIST?
	  JRST	MOVBT2		;NO, TRY NEXT
	MOVEI	T1,PM.ACC+PM.WRT(T2) ;GET NEXT PAGE TO ZERO
	HRLM	T1,EPT+.MZERO	;STORE IN MAP SLOT TO USE
IFN FTKL10!FTKS10,<
	CLRPT	.VZERO		;FLUSH PAGE TABLE FOR THAT PAGE
>
IFN FTKI10,<
	MOVE	T1,CPEBR	;GET EPT MAPPING
	XCT	CHGEBR		;CAUSE PAGE TABLE TO BE FLUSHED
>
	MOVE	T3,[.VZERO,,.VZERO+1] ;SETUP BLT POINTER
	SKIPN	T2		;ABOUT TO DO PAGE 0?
IFN FTKI10,<
	ADD	T3,[40,,40]	;YES, DON'T CLEAR 0-37
>
IFN FTKL10!FTKS10,<
	ADJSP	T3,40		;YES, DON'T CLEAR 0-37
>
	SETZM	-1(T3)		;CLEAR FIRST WORD OF PAGE
	BLT	T3,.VZERO+PAGSIZ-1 ;DO IT ALL
MOVBT2:	SOJGE	T2,MOVBT1	;LOOP IF MORE TO DO
	POPJ	P,		;RETURN
	SUBTTL	NXMTAB HANDLING ROUTINES ;⊗ FINDHI FINDH1 FINDH2 FNDPGS FNDPG1 FNDPG2


;ROUTINE TO FIND MBTPGS CONTIGUOUS PAGES STARTING AT THE TOP OF
;CORE SO THAT WE CAN MOVE BOOT THERE.
;CALL:	PUSHJ	P,FINDHI
;RETURN+1 ALWAYS WITH STARTING PAGE NUMBER IN T2

FINDHI:	MOVE	T2,MEMPSZ	;GET NUMBER OF PAGES IN CORE
FINDH1:	MOVEI	T1,BOOPGS	;NUMBER OF CONTIGUOUS PAGES WE NEED
FINDH2:	SOS	T2		;DECREMENT PAGE NUMBER
	PUSHJ	P,CHKNXM	;DOES THIS PAGE EXIST?
	  JRST	FINDH1		;NO, RESET COUNT AND TRY AGAIN
	SOJG	T1,FINDH2	;YES, DECREMENT PAGE AND CHECK IT
	POPJ	P,		;FOUND THEM, RETURN PAGE # IN T2


;ROUTINE TO FIND A CONTIGUOUS GROUP OF PAGES WHICH EXIST BY LOOKING
;THROUGH NXMTAB.  I KNOW THAT THIS ISN'T PARTICULARLY FAST BUT I WAS
;IN A HURRY.
;CALL:
;	P2/PAGE NUMBER OF WHERE TO START
;	PUSHJ	P,FNDPGS
;RETURN+1 ALWAYS
;RETURNS P1=COUNT OF PAGES
;	 P2=STARTING PAGE NUMBER

FNDPGS:	MOVEI	P1,0		;START WITH NO PAGES FOUND
	SOS	P2		;TAKE A RUNNING START AT THE LOOP
FNDPG1:	AOS	T2,P2		;INCREMENT PAGE NUMBER, COPY TO T2
	CAML	T2,MEMPSZ	;OFF THE END OF MEMORY?
	POPJ	P,		;YES, RETURN WITH P1=0
	PUSHJ	P,CHKNXM	;DOES THAT PAGE EXIST?
	  JRST	FNDPG1		;NO, LOOP FOR NEXT
FNDPG2:	CAMGE	T2,MEMPSZ	;OFF THE END OF MEMORY?
	PUSHJ	P,CHKNXM	;NO, DOES THIS PAGE EXIST?
	  POPJ	P,		;NO, RETURN
	AOS	P1		;INCREMENT COUNT OF PAGES
	AOJA	T2,FNDPG2	;INCREMENT PAGE NUMBER AND LOOP
;ROUTINE TO CHECK NXMTAB TO SEE IF A PAGE EXISTS. ;⊗ CHKNXM SUNXMT SUNXM1 SUNXM2
;CALL:
;	T2/PHYSICAL PAGE NUMBER
;	PUSHJ	P,CHKNXM
;RETURN+1 IF MARKED AS NXM
;RETURN+2 IF NOT
;PRESERVES T2, DESTROYS T3

CHKNXM:	PUSH	P,T2		;SAVE PAGE NUMBER
	IDIVI	T2,↑D36		;DIVIDE BY THE NUMBER OF BITS PER WORD
	MOVE	T2,NXMTAB(T2)	;GET THE WORD CONTAINING THE BIT
	LSH	T2,(T3)		;SHIFT NXM BIT TO 1B0
	SKIPL	T2		;MARKED AS A NXM?
	AOS	-1(P)		;NO, GIVE SKIP RETURN
	POP	P,T2		;RESTORE T2
	POPJ	P,		;RETURN


;ROUTINE TO BUILD NXMTAB BY TOUCHING EVERY POSSIBLE PAGE IN MEMORY
;TO SEE IF IT EXISTS.
;CALL:	PUSHJ	P,SUNXMT
;RETURN+1 ALWAYS

SUNXMT:	PUSHJ	P,SAVE2		;SAVE P1-P2
	SETZM	NXMTAB		;ZERO FIRST WORD OF NXMTAB
	MOVE	T1,[NXMTAB,,NXMTAB+1] ;GET BLT POINTER
	BLT	T1,NXMTBE	;ZERO IT ALL
IFN FTKL10!FTKS10,<
	PUSH	P,EPT+.LMPFN	;SAVE PAGE FAIL NEW PC
	MOVEI	T1,REFTRP	;NEED NEW PC SINCE NXM'S SOMETIMES
	MOVEM	T1,EPT+.LMPFN	;  CAUSE AR/ARX PARITY ERRORS
>
	MOVSI	P1,-MAXPGS	;GET LOOP COUNT FOR ALL POSSIBLE PAGES
	MOVEI	P2,0		;P2 WILL BE HIGHEST PAGE SEEN
	MOVE	T2,[POINT 1,NXMTAB] ;GET BYTE POINTER TO NXMTAB
	MOVEI	T3,1		;AND A BIT TO USE
SUNXM1:	IBP	T2		;STEP BYTE POINTER TO NEXT BIT
	PUSHJ	P,REFMEM	;TOUCH THAT PAGE
	  SKIPA	P2,P1		;EXISTS, MOVE NUMBER TO P2
	DPB	T3,T2		;SET THE BIT FOR THIS PAGE
	AOBJN	P1,SUNXM1	;LOOP FOR ALL PAGES
	ADDI	P2,1		;P2:=NUMBER OF PAGES IN MEMORY
	HRRZM	P2,MEMPSZ	;STORE FOR LATER
SUNXM2:	IDPB	T3,T2		;STORE 1'S IN THE REST
	TLNE	T2,(77B5)	;  OF THE FINAL
	JRST	SUNXM2		;  WORD
IFN FTKL10!FTKS10,<
	POP	P,EPT+.LMPFN	;RESTORE OLD PAGE FAIL TRAP ADDRESS
>
	CONO	APR,CLRAPR	;CLEAR APR ERRORS
	POPJ	P,		;AND RETURN
;ROUTINE TO DETERMINE IF A PAGE EXISTS IN MEMORY BY TOUCHING ;⊗ REFMEM REFTRP
;THAT PAGE.  NOTE THAT THE PAGE FAIL TRAP ADDRESS IN THE UPT HAS
;BEEN CHANGED TO POINT AT REFTRP BY THE CALLER.
;CALL:
;	P1/PHYSICAL PAGE NUMBER
;	PUSHJ	P,REFMEM
;RETURN+1 IF PAGE EXISTS
;RETURN+2 IF PAGE DOES NOT EXIST

REFMEM:	CONO	APR,CLRAPR	;CLEAR APR ERRORS
	MOVEI	T1,PM.ACC!PM.WRT(P1) ;GET MAP ENTRY FOR PAGE
	HRLM	T1,EPT+.MZERO	;USE .VZERO AS TEMPORARY PAGE
IFN FTKL10!FTKS10,<
	CLRPT	.VZERO		;FLUSH THE PAGE TABLE FOR THAT PAGE
>
IFN FTKI10,<
	MOVE	T1,CPEBR	;GET CURRENT EPT MAPPING
	XCT	CHGEBR		;FLUSH THE PAGE TABLE
>
	MOVES	.VZERO		;TOUCH THE PAGE
REFTRP:
IFN FTKI10,<
	CONSZ	APR,IP.NXM	;SEE A NXM?
>
IFN FTKL10,<
	CONSZ	APR,LP.NXM	;SEE A NXM?
>
IFN FTKS10,<
	CONSZ	APR,SP.NXM	;SEE A NXM?
>
	AOS	0(P)		;YES, GIVE SKIP RETURN
	POPJ	P,		;RETURN
	SUBTTL	TRAP HANDLING ;⊗ TRAP PFTRAP PFTRA1


;HERE ON A TRAP OTHER THAN A PAGE FAIL.

TRAP:	MOVEI	T1,[ASCIZ/?Trap other than page fail
MUUO = /]
	PUSHJ	P,PRMSG
	MOVE	T4,EPT+.UPMUO	;GET MUUO
	PUSHJ	P,PRHWD		;PRINT AS HALF WORDS
	MOVEI	T1,[ASCIZ/
MUUO PC = /]
	PUSHJ	P,PRMSG
	MOVE	T4,EPT+.UPMUP	;GET OLD PC WORD
	PUSHJ	P,PRHWD		;PRINT AS HALF WORDS
	JRST	PFTRA1		;JOIN COMMON EXIT CODE


;HERE ON A PAGE FAIL TRAP

PFTRAP:
IFN FTKI10,<
	EXP	0		;JSR HERE ON A KI
>
	MOVEI	T1,[ASCIZ/?Page fail trap
PFW = /]
	PUSHJ	P,PRMSG		;PRINT ERROR MESSAGE
IFN FTKI10,<
	MOVE	T4,EPT+.UPEPF	;GET PAGE FAIL WORD
>
IFN FTKL10!FTKS10,<
	MOVE	T4,EPT+.LMPFW	;GET PAGE FAIL WORD
>
	PUSHJ	P,PRHWD		;PRINT AS HALF-WORDS
	MOVEI	T1,[ASCIZ/
PF PC = /]
	PUSHJ	P,PRMSG	
IFN FTKI10,<
	MOVE	T4,PFTRAP	;GET PC OF FAILURE
>
IFN FTKL10!FTKS10,<
	MOVE	T4,EPT+.LMPFP	;GET PC OF FAILURE
>
	PUSHJ	P,PRHWD		;PRINT IT AS HALF WORDS
PFTRA1:	PUSHJ	P,PRTAPR	;PRINT APR STATUS
	JRST	RLDMON		;RESTART AT THE BEGINNING
;ROUTINE TO PRINT THE CONI APR AND RDERA (IF A KL10). ;⊗ PRTAPR
;CALL:	PUSHJ	P,PRTAPR
;RETURN+1 ALWAYS

PRTAPR:	MOVEI	T1,[ASCIZ/
CONI APR, = /]
	PUSHJ	P,PRMSG
	CONI	APR,T4		;GET CONI APR
	PUSHJ	P,PRHWD		;PRINT AS HALF WORDS
IFN FTKL10,<
	MOVEI	T1,[ASCIZ/
RDERA = /]
	PUSHJ	P,PRMSG
	RDERA	T4		;GET ERA
	PUSHJ	P,PRHWD		;PRINT AS HALF WORDS
>
	PJRST	PRCRLF		;END LINE AND RETURN
	SUBTTL	COMMAND PARSING ;⊗ PARSE PARSE1 PARSE2 PARSE3 CMDERR TRMTAB TRMTBL


;ROUTINE TO PARSE A COMMAND LINE.
;RETURNS WITH THE FILESPEC VARIABLE AND BITS IN S SETUP.
;CALL:	PUSHJ	P,PARSE
;RETURN+1 IF ERROR DETECTED AND MESSAGE ISSUED
;RETURN+2 IF NO ERRORS DETECTED

PARSE:	SETZM	FILSPC		;CLEAR FIRST WORD OF FILESPEC
	MOVE	T1,[FILSPC,,FILSPC+1] ;SETUP FOR BLT
	BLT	T1,FILSPE	;CLEAR IT ALL
	TDZA	S,[FX.CLR]	;CLEAR FLAG BITS AND GET FIRST ATOM
PARSE1:	TDZA	T1,T1		;CLEAR ATOM, SKIP CALL TO GETSIX
PARSE2:	PUSHJ	P,GETSIX	;GET SIXBIT ATOM IN T1
	MOVSI	T2,-TRMTBL	;-VE LENGTH OF TERMINATING CHAR TABLE
PARSE3:	HLRZ	T4,TRMTAB(T2)	;GET NEXT POSSIBLE CHARACTER FROM TABLE
	CAIE	T4,(T3)		;MATCH WITH THE ONE WE SAW?
	AOBJN	T2,PARSE3	;NO, LOOP
	HRRZ	T4,TRMTAB(T2)	;GET DISPATCH ADDRESS FOR ATOM
	JUMPL	T2,(T4)		;GO TO ROUTINE IF MATCH FOUND
CMDERR:	MOVEI	T1,[ASCIZ/%Syntax error
/]
	PJRST	PRMSG		;TELL OF ERROR AND RETURN


;TABLE OF LEGAL CHARACTERS TERMINATING COMMAND STRING ATOMS AND
;THE CORRESPONDING DISPATCH ADDRESSES.  FORMAT IS:
;	XWD	CHAR,ADDRESS

TRMTAB:	XWD	":",CMDDEV	;DEVICE SEEN
	XWD	".",CMDFIL	;FILENAME SEEN
	XWD	"[",CMDPTH	;START OF PATCH SEEN
	XWD	"/",CMDSWT	;SWITCH SEEN
	XWD	.CHCRT,CMDEOL	;END OF LINE SEEN
TRMTBL==.-TRMTAB		;LENGTH OF TABLE
;HERE TO PROCESS DEVICE IN COMMAND STRING ;⊗ CMDDEV CMDFIL CMDPTH CMDPT1 CMDPT2

CMDDEV:	TRON	S,FR.DEV	;ALREADY HAVE A DEVICE?
	SKIPN	T1		;NO, DEVICE NULL?
	JRST	CMDERR		;YES, ERROR
	MOVEM	T1,DEV		;STORE DEVICE
	JRST	PARSE2		;AND GET NEXT ATOM


;HERE TO PROCESS FILENAME IN COMMAND STRING

CMDFIL:	JSP	T2,STOFIL	;STORE FILENAME AS NECESSARY
	TROE	S,FR.EXT	;FLAG AN EXTENSION SEEN
	JRST	CMDERR		;ERROR IF MORE THAN ONE
	PUSHJ	P,GETSIX	;GET EXTENSION
	HLLZM	T1,EXT		;STORE IT
	JRST	PARSE1		;GET NEXT ATOM


;HERE TO PROCESS PATH SPEC IN COMMAND STRING

CMDPTH:	JSP	T2,STOFIL	;STORE FILENAME AS NECESSARY
	PUSHJ	P,GETOCT	;GET OCTAL PROJECT NUMBER
	JUMPE	T1,CMDERR	;NONE IS ILLEGAL
	TRON	S,FR.PTH	;ALREADY SEEN A PATH?
	CAIE	T3,","		;MUST HAVE BROKEN ON A COMMA
	JRST	CMDERR		;ELSE ERROR
	HRLZM	T1,PTHBLK	;STORE IN PATH BLOCK
	PUSHJ	P,GETOCT	;GET PROGRAM NUMBER
	JUMPE	T1,CMDERR	;NONE IS ILLEGAL
	HRRM	T1,PTHBLK	;STORE IN PATH BLOCK
	MOVSI	W,-LIMLVL	;SETUP AOBJN POINTER TO SFD'S
CMDPT1:	CAIE	T3,","		;SFD COMMING?
	JRST	CMDPT2		;NO, OR NONE ALLOWED
	PUSHJ	P,GETSIX	;GET SFD NAME
	JUMPE	T1,CMDERR	;MUST NOT BE NULL
	MOVEM	T1,PTHBLK+1(W)	;STORE IN NEXT SLOT IN PATH BLOCK
	AOBJN	W,CMDPT1	;LOOP FOR NEXT
CMDPT2:	CAIN	T3,"]"		;TERMINATE WITH RIGHT BRACKET?
	JRST	PARSE2		;YES, GET NEXT ATOM
	JRST	PARSE1		;NO, WORRY ABOUT THE CHARACTER
;HERE TO PROCESS THE END OF THE COMMAND LINE ;⊗ CMDEOL

CMDEOL:	JSP	T2,STOFIL	;STORE FILENAME AS NECESSARY
	MOVSI	T1,'DSK'	;GET GENERIC DISK
	TRNE	S,FR.DEV	;DEVICE SEEN?
	CAMN	T1,DEV		;OR GENERIC DISK?
	TLO	S,(FL.WLD)	;YES, FLAG IT
	MOVSI	T1,'EXE'	;DEFAULT EXTENSION IS EXE
	TRNN	S,FR.EXT	;EXTENSION SEEN?
	MOVEM	T1,EXT		;NO, USE DEFAULT
	MOVE	T1,[1,,4]	;DEFAULT DIRECTORY IS [1,4]
	TRNN	S,FR.PTH	;PATH SEEN?
	MOVEM	T1,PTHBLK	;NO, STORE DEFAULT
	JRST	CPOPJ1		;GIVE SKIP RETURN
;HERE TO PROCESS A SWITCH IN THE COMMAND STRING ;⊗ CMDSWT CMDSW1 CMDSW2 SWTTAB SWTTBL

CMDSWT:	JSP	T2,STOFIL	;STORE FILENAME AS NECESSARY
	PUSHJ	P,GETSIX	;GET THE SWITCH
	MOVE	T2,T1		;COPY IT TO T2
	SETOM	W		;SET FULL WORD MASK
CMDSW1:	LSH	W,-6		;SHIFT MASK 6
	LSH	T2,6		;AND WORD BY SAME AMOUNT
	JUMPN	T2,CMDSW1	;UNTIL IT'S NULL
	MOVSI	T4,-SWTTBL	;GET -VE LENGTH OF SWITCH TABLE
CMDSW2:	MOVE	T2,SWTTAB(T4)	;GET NEXT ENTRY IN SWITCH TABLE
	TDZ	T2,W		;MASK TO SAME SIZE AS WHAT USER TYPED
	CAME	T1,T2		;MATCH?
	AOBJN	T4,CMDSW2	;NO, LOOP FOR NEXT
	TLZN	T4,-1		;CLEAR LH.  FIND MATCH?
	JRST	CMDERR		;NO
	MOVEI	T1,FR.1ST	;GET FIRST SWITCH BIT IN S
	LSH	T1,(T4)		;SHIFT BY OFFSET INTO SWITCH TABLE
	IORI	S,(T1)		;SET SWITCH BIT IN S
	CAIE	T3,":"		;SWITCH HAVE A VALUE?
	JRST	PARSE1		;NO, GET NEXT ATOM
	CAIL	T4,SWTVLL	;CAN THIS SWITCH LEGALLY HAVE A VALUE?
	JRST	CMDERR		;NO
	PUSHJ	P,GETOCT	;GET OCTAL VALUE FOR SWITCH
	MOVEM	T1,SWTVAL(T4)	;STORE VALUE IN TABLE
	JRST	PARSE1		;AND GET NEXT ATOM


;TABLE OF LEGAL SWITCHES.  NOTE THAT ALL SWITCHES THAT MAY HAVE
;AN OCTAL VALUE MUST OCCUR POSITIONALLY BEFORE THE SWTVLL'TH
;LOCATION IN THE TABLE.

SWTTAB:	SIXBIT/START/		;/START:N
	SIXBIT/LOAD/		;/LOAD
	SIXBIT/DUMP/		;/DUMP
	SIXBIT/REBOOT/		;/REBOOT
SWTTBL==.-SWTTAB
	SUBTTL	COMMAND	INPUT ;⊗ STOFIL GETSIX GETSI1 GETSI2 GETOCT GETOC1


;ROUTINE TO STORE A FILENAME IF REQUIRED.
;CALL:
;	T1/FILENAME OR 0
;	JSP	T2,STOFIL
;RETURN+1 IF NO ERRORS

STOFIL:	JUMPE	T1,(T2)		;DON'T DO ANYTHING IF NOTHING TO STORE
	TROE	S,FR.FIL	;ALREADY SEEN A FILENAME?
	JRST	CMDERR		;YES, ERROR
	MOVEM	T1,FILNAM	;STORE FILENAME
	JRST	(T2)		;AND RETURN


;ROUTINE TO READ A SIXBIT NAME FROM THE COMMAND STRING.
;CALL:	PUSHJ	P,GETSIX
;RETURN+1 ALWAYS
;RETURNS NAME IN T1, BREAK CHARACTER IN T3
;DESTROYS T2

GETSIX:	MOVEI	T1,0		;START WITH NULL NAME
	MOVE	T2,[POINT 6,T1]	;GET BYTE POINTER FOR ATOM
GETSI1:	PUSHJ	P,GETCHR	;GET NEXT CHARACTER FROM COMMAND
	CAIL	T3,"A"		;LETTER?
	CAILE	T3,"Z"		; ??
	CAIA			;NO, CHECK DIGITS
	JRST	GETSI2		;YES
	CAIL	T3,"0"		;NUMBER?
	CAILE	T3,"9"		; ??
	POPJ	P,		;NO, RETURN
GETSI2:	TRC	T3,"A"-'A'	;CONVERT ASCII TO SIXBIT
	TLNE	T2,770000	;TOO MANY?
	IDPB	T3,T2		;NO, STORE IN T1
	JRST	GETSI1		;AND LOOP FOR NEXT


;ROUTINE TO RETURN AN OCTAL NUMBER FROM THE COMMAND STRING.
;CALL:	PUSHJ	P,GETOCT
;RETURN+1 ALWAYS
;RETURNS NUMBER IN T1, BREAK CHARACTER IN T3

GETOCT:	MOVEI	T1,0		;START WITH NO NUMBER
GETOC1:	PUSHJ	P,GETCHR	;GET NEXT CHARACTER FROM COMMAND
	CAIL	T3,"0"		;NUMBER?
	CAILE	T3,"7"		;  OCTAL THAT IS?
	POPJ	P,		;NO, RETURN
	LSH	T1,3		;MAKE ROOM FOR IT
	IORI	T1,-"0"(T3)	;INCLUDE IN TOTAL
	JRST	GETOC1		;LOOP FOR NEXT
;ROUTINE TO RETURN THE NEXT CHARACTER FROM THE COMMAND STREAM. ;⊗ GETCHR ASKYN CPOPJ1 CPOPJ
;CONVERTS LOWER TO UPPER CASE.
;CALL:	PUSHJ	P,GETCHR
;RETURN+1 ALWAYS WITH CHARACTER IN T3

GETCHR:	ILDB	T3,CMDPTR	;READ CHARACTER FROM COMMAND BUFFER
	CAIE	T3," "		;SPACE?
	CAIN	T3,.CHTAB	;  OR TAB?
	MOVEI	T3,.CHCRT	;YES, RETURN CR
	CAIL	T3,"a"		;LOWER CASE?
	CAILE	T3,"z"		;??
	POPJ	P,		;NO
	SUBI	T3,"a"-"A"	;YES, CONVERT TO UPPER
	POPJ	P,		;AND RETURN


;ROUTINE TO ASK A QUESTION AND GIVE SKIP RETURN IF ANSWER WAS YES.
;CALL:
;	T1/ADDRESS OF QUESTION STRING
;	PUSHJ	P,ASKYN
;RETURN+1 IF ANSWER WAS NO (REALLY NOT YES)
;RETURN+2 IF ANSWER WAS YES

ASKYN:	PUSHJ	P,REDLIN	;ASK QUESTION, READ ANSWER
	PUSHJ	P,GETCHR	;GET FIRST CHARACTER
	CAIN	T3,"Y"		;YES?
CPOPJ1:	AOS	0(P)		;YES, GIVE SKIP RETURN
CPOPJ:	POPJ	P,		;RETURN
;ROUTINE TO PRINT A PROMPT STRING, AND READ A COMMAND LINE INTO ;⊗ REDLIN REDLI1 REDLI2 TPOPJ
;CMDBUF.  DOES LOCAL EDITING OF RUBOUT AND ↑U.
;CALL:
;	T1/ADDRESS OF PROMPT STRING
;	PUSHJ	P,REDLIN
;RETURN+1 ALWAYS WITH LINE IN CMDBUF


REDLIN:	PUSHJ	P,SAVE2		;SAVE P1-P2
	PUSH	P,T1		;SAVE ADDRESS OF PROMPT STRING
REDLI1:	MOVE	T1,0(P)		;RESTORE ADDRESS FOR SUBSEQUENT TIMES
	PUSHJ	P,PRMSG		;TYPE PROMPT STRING
	MOVE	P1,[POINT 7,CMDBUF] ;GET POINTER TO BUFFER
	MOVEM	P1,CMDPTR	;SAVE FOR CALLER
	SETZM	CMDBUF		;SET TO CLEAR BUFFER
	MOVE	T1,[CMDBUF,,CMDBUF+1] ;SETUP FOR BLT
	BLT	T1,CMDBUF+LINBFL-1 ;ZERO IT ALL
	TLZ	S,(FL.RUB)	;CLEAR RUBOUT FLAG
	MOVEI	P2,<LINBFL*5>-5 ;MAX CHARACTERS
REDLI2:	PUSHJ	P,TYI		;READ A CHARACTER
	CAIE	T3,.CHCNH	;BACKSPACE?
	CAIN	T3,.CHDEL	; OR RUBOUT?
	JRST	REDRUB		;YES
	CAIN	T3,.CHCNU	;↑U?
	JRST	REDCNU		;YES
	CAIE	T3,.CHCRT	;END OF LINE?
	SOSL	P2		;IGNORE IF TOO MANY
	IDPB	T3,P1		;STASH CHAR
	TLZE	S,(FL.RUB)	;POST PROCESS RUBOUT
	PUSHJ	P,PRBSL		;BY PRINTING BACKSLASH
	LDB	T3,P1		;GET CHAR BACK
	PUSHJ	P,ECHO		;AND ECHO CHARACTER
	LDB	T3,P1		;ONCE MORE
	CAIE	T3,.CHCRT	;END-OF LINE?
	JRST	REDLI2		;NO, LOOP
TPOPJ:	POP	P,T1		;RESTORE T1
	POPJ	P,		;AND RETURN
;HERE TO PROCESS RUBOUTS ;⊗ REDRUB REDRU1 REDCNU REDCU1

REDRUB:	CAIN	P2,<LINBFL*5>-5	;CHECK FOR BEGINNING OF LINE
	JRST	REDRU1		;YES
	TLON	S,(FL.RUB)	;CHECK HERE BEFORE?
	PUSHJ	P,PRBSL		;NO, TYPE BACKSLASH
	LDB	T3,P1		;GET CHAR
	PUSHJ	P,ECHO		;PRINT IT
IFN FTKI10,<
	ADD	P1,[POINT 0,0,28] ;BACK UP BYTE PNTR
	TLNE	P1,(1B0)
	SUB	P1,[POINT 0,1,0]
>
IFN FTKL10!FTKS10,<
	MOVNI	T3,1		;WANT TO BACKUP POINTER BY
	EXCH	T3,P1		;BY 1 BYTE POSITION
	ADJBP	P1,T3		;DO IT THE EASY WAY
>
	AOJA	P2,REDLI2	;GET NEXT CHAR

;HERE TO PROCESS BEGINNING OF LINE ON RUBOUT

REDRU1:	TLZE	S,(FL.RUB)	;NEED TO TYPE A BACKSLASH?
	PUSHJ	P,PRBSL		;YES, DO SO
	JRST	REDCU1		;JOIN COMMON CODE

;HERE TO PROCESS ↑U

REDCNU:	PUSHJ	P,ECHO		;ECHO AS UPARROW U
REDCU1:	PUSHJ	P,PRCRLF	;TYPE CRLF
	JRST	REDLI1		;RETYPE PROMPT AND TRY AGAIN
	SUBTTL	COMMAND OUTPUT ;⊗ PRRBCR PRCRLF PRBSL PRCOMA PRLBKT PRRBKT PRMSG PRMSG1 PRSIX


;ROUTINES TO PRINT SELECTED CHARACTERS.
;
;	PRCRLF	- PRINT CRLF
;	PRBSL	- PRINT BACKSLASH
;	PRCOMA	- PRINT COMMA
;	PRLBKT	- PRINT LEFT BRACKET
;	PRRBKT	- PRINT RIGHT BRACKET
;	PRRBCR	- PRINT RIGHT BRACKET AND CRLF

PRRBCR:	PUSHJ	P,PRRBKT	;PRINT RIGHT BRACKET AND FALL INTO PRCRLF
PRCRLF:	MOVEI	T3,.CHCRT	;GET A CR
	PUSHJ	P,TYO
	MOVEI	T3,.CHLFD	;GET A LF
	PJRST	TYO		;TYPE IT AND RETURN

PRBSL:	SKIPA	T3,["\"]	;GET A BACKSLASH
PRCOMA:	MOVEI	T3,","		;GET A COMMA
	PJRST	TYO		;TYPE IT AND RETURN
PRLBKT:	SKIPA	T3,["["]	;GET A LEFT BRACKET
PRRBKT:	MOVEI	T3,"]"		;GET A RIGHT BRACKET
	PJRST	TYO		;TYPE IT AND RETURN


;ROUTINE TO PRINT AN ASCIZ MESSAGE ON THE CTY.
;CALL:
;	T1/ADDRESS OF ASCIZ STRING
;	PUSHJ	P,PRMSG
;RETURN+1 ALWAYS
;DESTROYS T1,T3

PRMSG:	HRLI	T1,(POINT 7,)	;FORM 7 BIT BYTE POINTER
PRMSG1:	ILDB	T3,T1		;GET NEXT CHARACTER
	JUMPE	T3,CPOPJ	;RETURN ON NULL
	PUSHJ	P,TYO		;TYPE CHARACTER
	JRST	PRMSG1		;LOOP FOR NEXT


;ROUTINE TO PRINT A SIXBIT WORD ON THE CTY.
;CALL:
;	T1/SIXBIT WORD
;	PUSHJ	P,PRSIX
;RETURN+1 ALWAYS
;DESTROYS T1,T2,T3

PRSIX:	LSHC	T1,-↑D36	;MOVE WORD TO T2, CLEAR T1
	LSHC	T1,6		;MOVE NEXT BYTE TO T1
	MOVEI	T3,"A"-'A'(T1)	;CONVERT TO ASCII AND COPY TO T3
	PUSHJ	P,TYO		;PUT IT OUT
	SKIPE	T1,T2		;MOVE REMAINDER BACK TO T1, SKIP IF DONE
	JRST	PRSIX		;LOOP FOR REST
	POPJ	P,		;RETURN
;ROUTINE TO PRINT AN OCTAL NUMBER ON THE CTY. ;⊗ PROCT PRHWD PRHWD1 PRHWD2 ECHO
;CALL:
;	T1/NUMBER TO PRINT
;	PUSHJ	P,PROCT
;RETURN+1 ALWAYS
;DESTROYS T1,T2,T3

PROCT:	IDIVI	T1,↑D8		;DIVIDE BY RADIX, REMAINDER IN T2
	HRLM	T2,0(P)		;STORE ON STACK
	SKIPE	T1		;DONE?
	PUSHJ	P,PROCT		;NO, LOOP
	HLRZ	T3,0(P)		;GET DIGIT FROM STACK
	ADDI	T3,"0"		;CONVERT TO ASCII
	PJRST	TYO		;OUTPUT IT AND RETURN TO CALLER


;ROUTINE TO PRINT A WORD AS TWO 6 DIGIT OCTAL NUMBERS SEPARATED
;BY TWO COMMAS.
;CALL:
;	T4/WORD
;	PUSHJ	P,PRHWD
;RETURN+1 ALWAYS

PRHWD:	PUSHJ	P,PRHWD1	;PRINT LEFT HALF
	MOVEI	T1,[ASCIZ/,,/]	;FOLLOWED BY
	PUSHJ	P,PRMSG		;  TWO COMMAS
PRHWD1:	MOVEI	T1,6		;LOOP COUNT IS 6
PRHWD2:	MOVE	T3,T4		;MOVE WORD TO T3
	LSHC	T3,-↑D33	;KEEP 1 DIGIT, CLEAR REST OF T3
	ADDI	T3,"0"		;CONVERT TO ASCII
	PUSHJ	P,TYO		;PUT IT OUT
	SOJG	T1,PRHWD2	;LOOP FOR ALL
	POPJ	P,		;RETURN


;ROUTINE TO PRINT ONE CHARACTER IN (POSSIBLY) UP-ARRROW FORMAT.
;CALL:
;	T3/CHARACTER TO ECHO
;	PUSHJ	P,ECHO
;RETURN+1 ALWAYS
;DESTROYS T3

ECHO:	CAIE	T3,.CHTAB	;TAB?
	CAIL	T3," "		;NO, CONTROL CHARACTER?
	PJRST	TYO		;NO, JUST PRINT IT
	CAIN	T3,.CHCRT	;END-OF-LINE?
	PJRST	PRCRLF		;YES, ECHO CRLF
	PUSH	P,T3		;SAVE CHAR
	MOVEI	T3,"↑"		;PRINT CTRL CHAR
	PUSHJ	P,TYO		;...
	POP	P,T3		;RESTORE CHARACTER
	ADDI	T3,"A"-1	;CONVERT TO PRINTING CHARACTER
	PJRST	TYO		;PRINT IT AND RETURN
;ROUTINE TO PRINT THE CURRENT FILESPEC FROM THE DATA BASE. ;⊗ PRFILE PRFIL1
;CALL:	PUSHJ	P,PRFILE
;RETURN+1 ALWAYS
;DESTROYS T1-T4

PRFILE:	MOVE	T1,DEV		;GET DEVICE NAME
	PUSHJ	P,PRSIX		;PRINT IT
	MOVEI	T3,":"		;GET A COLON
	PUSHJ	P,TYO		;PRINT IT
	MOVE	T1,FILNAM	;GET THE FILENAME
	PUSHJ	P,PRSIX		;PRINT IT
	MOVEI	T3,"."		;GET A DOT
	PUSHJ	P,TYO		;PRINT IT
	HLLZ	T1,EXT		;GET EXTENSION
	PUSHJ	P,PRSIX		;PRINT IT
	PUSHJ	P,PRLBKT	;PRINT LEFT BRACKET
	HLRZ	T1,PTHBLK	;GET PROJECT NUMBER
	PUSHJ	P,PROCT		;PRINT IT
	PUSHJ	P,PRCOMA	;PRINT COMMA
	HRRZ	T1,PTHBLK	;GET PROGRAMMER NUMBER
	PUSHJ	P,PROCT		;PRINT IT
	MOVEI	T4,1		;OFFSET INTO PTHBLK OF FIRST SFD
PRFIL1:	SKIPN	T1,PTHBLK(T4)	;NEXT SFD NON-NULL?
	PJRST	PRRBKT		;NO, PRINT RIGHT BRACKET AND RETURN
	PUSHJ	P,PRCOMA	;PRINT COMMA
	PUSHJ	P,PRSIX		;PRINT SFD NAME
	AOJA	T4,PRFIL1	;LOOP FOR NEXT SFD
	SUBTTL	LOWEST LEVEL CTY INPUT/OUTPUT ROUTINES ;⊗ TYO DODTE


;ROUTINE TO TYPE ONE CHARACTER ON THE CTY.
;CALL:
;	T3/CHARACTER TO TYPE
;	PUSHJ	P,TYO
;RETURN+1 ALWAYS
;DESTROYS T3.

TYO:
IFN FTKL10,<
	MOVSI	T3,DT.MTO(T3)	;GET CHAR IN LOW ORDER 8 BITS, COMMAND IN NEXT FOUR
	HRRI	T3,DTEMTD	;PUT WORD OFFSET IN RH
DODTE:	SETZM	EPT(T3)		;CLEAR DONE FLAG
	HLRZM	T3,EPT+DTECMD	;PUT INTO COMMAND LOCATION
	CONO	DTE0,TO11DB	;RING DOORBELL
	SKIPN	EPT(T3)		;WAIT TILL MONITOR OUTPUT DONE
	JRST	.-1		;LOOP
	POPJ	P,0		;DONE.
>;END IFN FTKL10

IFN FTKI10,<
	DATAO	TTY,T3		;SEND OUT CHAR
	CONSZ	TTY,IT.BSY	;WAIT FOR IDLE
	JRST	.-1		; ..
	POPJ	P,0		;DONE.
>;END IFN FTKI10

IFN FTKS10,<
	SKIPE	.VPAG0+CTYOWD	;CAN WE SEND NEXT CHAR?
	JRST	.-1		;NOT YET
	IORI	T3,CTYOVL	;SIGNAL VALID
	MOVEM	T3,.VPAG0+CTYOWD ;PUT IT UP FOR THE 8080 TO FIND IT
	WRAPR	SP.SSF!SP.IFE	;WAKE THE 8080
	POPJ	P,0		;DONE
>;END IFN FTKS10
;ROUTINE TO READ ONE CHARACTER FROM THE CTY. ;⊗ TYI BRKTAB
;CALL:	PUSHJ	P,TYI
;RETURN+1 ALWAYS WITH CHARACTER IN T3
;DESTROYS T1

TYI:
IFN FTKL10,<
	SKIPN	EPT+DTEMTI	;INPUT READY?
>
IFN FTKI10,<
	CONSO	TTY,IT.DON	;INPUT READY?
>
IFN FTKS10,<
	SKIPN	.VPAG0+CTYIWD	;INPUT READY?
>
	JRST	.-1		;NO, LOOP
IFN FTKL10,<
	MOVE	T3,EPT+DTEF11	;GET CHARACTER
	SETZM	EPT+DTEMTI	;FLAG WE GOT IT
>;END IFN FTKL10

IFN FTKI10,<
	DATAI	TTY,T3		;GET THE CHARACTER
>;END IFN FTKI10

IFN FTKS10,<
	MOVEI	T3,0		;SET TO GET CHAR AND CLEAR WORD
	EXCH	T3,.VPAG0+CTYIWD ;GET CHARACTER AND CLEAR
>;END IFN FTKS10

	ANDI	T3,177		;KEEP ONLY 7 BITS
	JUMPE	T3,TYI		;IGNORE NULLS
	MOVEI	T1,1		;GET A BIT TO SHIFT
	LSH	T1,(T3)		;SHIFT BY VALUE OF CHARACTER
	TDNE	T1,BRKTAB	;BREAK CHARACTER?
	MOVEI	T3,.CHCRT	;YES, CONVERT TO CR
	POPJ	P,		;RETURN

BRKTAB:	1←.CHBEL!1←.CHTAB!1←.CHLFD!1←.CHVTB!1←.CHFFD!1←.CHCNZ!1←.CHESC!1←" "
	SUBTTL	DISK SUPPORT SUBROUTINES ;⊗ REDREG DRVTYP DRVTY1


IFE FTKS10,<
;ROUTINE TO READ A MASSBUS REGISTER AND RETURN THE VALUE.
;CALL WITH:
;	T1/DATAO WORD
;	PUSHJ	P,REDREG
;RETURN+1 ALWAYS WITH FULL 36 BIT DATA IN T1

REDREG:	XCT	DODATO		;TELL THE DEVICE WHICH REGISTER
	STALL			;WAIT AWHILE
	XCT	DODATI		;READ THE DATA
	POPJ	P,		;RETURN
>;END IFE FTKS10


;ROUTINE TO READ AND CHECK THE DRIVE TYPE REGISTER FOR A DEVICE AGAINST
;THOSE DRIVE TYPES THAT WE KNOW ABOUT.
;CALL:
;	T1/DATAO WORD TO READ DRIVE TYPE REGISTER
;	PUSHJ	P,DRVTYP
;RETURN+1 IF NO MATCH
;RETURN+2 IF MATCH WITH DRVBPC, DRVBPT SETUP

DRVTYP:
IFE FTKS10,<
	PUSHJ	P,REDREG	;READ THE REGISTER
>
IFN FTKS10,<
	TRNN	T1,SI.DSK	;THIS A DISK UNIT?
	POPJ	P,		;NO
>
	ANDI	T1,777		;KEEP ONLY 9 BITS
	MOVSI	T2,-DRTTBL	;GET AOBJN POINTER TO DRIVE TYPE TABLE
DRVTY1:	CAME	T1,DRTTAB(T2)	;MATCH WITH THIS ONE?
	AOBJN	T2,DRVTY1	;NO, LOOP
	JUMPGE	T2,CPOPJ	;FAIL IF NO MATCH
	MOVE	T1,BPCTAB(T2)	;GET BLOCKS/CYLINDER
	MOVE	T2,BPTTAB(T2)	;  AND BLOCKS/TRACK
	DMOVEM	T1,DRVBPC	;STORE VALUES
	JRST	CPOPJ1		;GIVE SKIP RETURN
;TABLES DEFINING THE DRIVE TYPES OF THE DRIVES WE KNOW ABOUT AND ;⊗ DRTTAB DRTTBL BPCTAB BPTTAB
;THE CORRESPONDING VALUES OF BLOCKS/CYLINDER AND BLOCKS/TRACK FOR
;EACH DRIVE.  THESE ARE PARALLEL TABLES AND THUS ARE ORDER SENSITIVE.
;
;TABLE GIVING THE DRIVE TYPES THAT WE KNOW ABOUT.

DRTTAB:	EXP	20		;RP04
	EXP	22		;RP06
	EXP	24		;RM03
	EXP	42		;RP07
DRTTBL==.-DRTTAB


;TABLE GIVING THE NUMBER OF BLOCKS/CYLINDER FOR EACH DRIVE.

BPCTAB:	DEC	380		;RP04
	DEC	380		;RP06
	DEC	150		;RM03
	DEC	1376		;RP07


;TABLE GIVING THE NUMBER OF BLOCKS/TRACK FOR EACH DRIVE.

BPTTAB:	DEC	20		;RP04
	DEC	20		;RP04
	DEC	30		;RM03
	DEC	43		;RP07
	SUBTTL	BYTE POINTERS INTO DATA STRUCTURES ;⊗ DESRBU DENRBU DESRBA DENRBA DEYRBU DEYRBA


DESRBU==↑D4	;SIZE OF UNIT NUMBER FIELD IN RIBXRA
DENRBU==↑D12	;BIT POSITION OF UNIT NUMBER FIELD IN RIBXRA
DESRBA==↑D23	;SIZE OF CLUSTER ADDRESS FIELD IN RIBXRA
DENRBA==↑D35	;BIT POSITION OF CLUSTER ADDRESS FIELD IN RIBXRA

DEYRBU:	POINT	DESRBU,RIB+RIBXRA,DENRBU
		;UNIT ON WHICH NEXT EXTENDED RIB EXISTS
DEYRBA:	POINT	DESRBA,RIB+RIBXRA,DENRBA
		;CLUSTER ADDRESS ON UNIT ON WHICH NEXT EXTENDED
		;RIB EXISTS
	SUBTTL	TABLES DRIVING DEVICE DEPENDENT I/O ;⊗ DVCTAB DVCTBL IOTTAB DODATO DODATI DOCONI DOCONO DOCNSO IOTTBL


;TABLE GIVING DEVICE CODES OF CONTROLLERS THAT WE CAN TALK TO.
;TABLE IS ORDERED (HOPEFULLY) SO THAT WE WILL FIND THE FILE IN THE
;LEAST DISK ACCESSES.
;FORMAT IS:
;	XWD	<OFFSET INTO TYPE TABLES>,<DEVICE CODE>←-2

DEFINE	DCODE(CODE,OFS,FTS),<
	IFN	FTS,<
	XWD	OFS,CODE←-2
	>
>

DVCTAB:	DCODE	(540,R20OFS,FTKL10)	;RH20 0 ON KL
	DCODE	(544,R20OFS,FTKL10)	;RH20 1 ON KL
	DCODE	(550,R20OFS,FTKL10)	;RH20 2 ON KL
	DCODE	(554,R20OFS,FTKL10)	;RH20 3 ON KL
	DCODE	(270,R10OFS,FTKI10!FTKL10) ;RH10 0 ON KI OR KL
	DCODE	(274,R10OFS,FTKI10!FTKL10) ;RH10 1 ON KI OR KL
	DCODE	(560,R20OFS,FTKL10)	;RH20 4 ON KL
	DCODE	(564,R20OFS,FTKL10)	;RH20 5 ON KL
	DCODE	(570,R20OFS,FTKL10)	;RH20 6 ON KL
	DCODE	(574,R20OFS,FTKL10)	;RH20 7 ON KL
	DCODE	(360,R10OFS,FTKI10!FTKL10) ;RH10 2 ON KI OR KL
	DCODE	(364,R10OFS,FTKI10!FTKL10) ;RH10 3 ON KI OR KL
	DCODE	(<1←2>,R11OFS,FTKS10)	;RH11 UBA 1 ON KS
DVCTBL==.-DVCTAB


;TABLE OF I/O INSTRUCTIONS.  DEVICE CODES FILLED IN BEFORE USE.

IOTTAB:
IFN FTKI10!FTKL10,<
DODATO:	DATAO	0,T1
DODATI:	DATAI	0,T1
DOCONI:	CONI	0,T1
DOCONO:	CONO	0,(T1)
DOCNSO:	CONSO	0,(T1)
>;END IFN FTKI10!FTKL10
IOTTBL==.-IOTTAB
;THE FOLLOWING TABLES GIVE THE DISPATCH ADDRESSES FOR THE CONTROLLER ;⊗ OFS REDTAB WRTTAB
;DEPENDENT READ AND WRITE ROUTINES.  ALL ARE CALLED WITH THE FOLLOWING
;AC'S SETUP:
;
; J = INDEX INTO DEVICE CODE TABLE
; U = PHYSICAL UNIT NUMBER
; W = OFFSET INTO TABLES BELOW
; R = PHYSICAL MEMORY ADDRESS OF START OF TRANSFER
; F = BLOCK ON UNIT OF FIRST BLOCK TO TRANSFER
; M = NUMBER OF CONTIGUOUS BLOCKS TO TRANSFER
;
;ALL CONTROLLER DEPENDENT ROUTINES MUST PRESERVE F AND R WITH
;A CALL TO SAVFR.
;
;**** THE RH10 AND RH20 ENTRIES IN THE FOLLOWING TABLES MUST BE
;**** THE FIRST AND SECOND ENTRIES IN THE TABLES AND MUST REMAIN
;**** IN THE SAME RELATIVE ORDER.


DEFINE	DADDR(ADDR,OFS,FTS),<
	IFN	FTS,<
	OFS==.-REDTAB
	EXP	ADDR
	>
>


;TABLE OF ADDRESSES OF CONTROLLER READ ROUTINES INDEXED BY CONTROLLER
;TYPE.

REDTAB:	DADDR	(R12RED,R10OFS,FTKI10!FTKL10)
	DADDR	(R12RED,R20OFS,FTKL10)
	DADDR	(R11RED,R11OFS,FTKS10)


DEFINE	DADDR	(ADDR,FTS),<
	IFN	FTS,<
	EXP	ADDR
	>
>


;TABLE OF ADDRESSES OF CONTROLLER WRITE ROUTINES INDEXED BY CONTROLLER
;TYPE.

WRTTAB:	DADDR	(R12WRT,FTKI10!FTKL10)
	DADDR	(R12WRT,FTKL10)
	DADDR	(R11WRT,FTKS10)
IFN FTKL10!FTKI10,< ;⊗ R12WRT R12RED R12XFR R10XFR R12XF1
	SUBTTL	RH10/RH20 DEVICE DEPENDENT ROUTINES


;ROUTINES TO READ FROM/WRITE TO A DRIVE ON AN RH10/RH20. CALL WITH THE
;STANDARD AC'S SETUP.  TRANSLATES THE DEVICE INDEPENDENT TRANSFER
;REQUEST INTO AS MANY TRANSFERS AS NECESSARY TO MAKE THE RH10/RH20 HAPPY.
;CALL:	PUSHJ	P,R12RED -OR- PUSHJ   P,R12WRT
;RETURN+1 IF I/O ERRORS
;RETURN+2 IF TRANSFER WAS SUCCESSFUL

R12WRT:	TLOA	S,(FL.IO)	;SET FLAG FOR OUTPUT
R12RED:	TLZ	S,(FL.IO)	;CLEAR FLAG FOR INPUT
	PUSHJ	P,SAVFR		;SAVE F AND R
	PUSHJ	P,R12INI	;INITIALIZE THE RH10/RH20
	  POPJ	P,		;FAILED
R12XFR:	JUMPLE	M,CPOPJ1	;DONE WHEN TRANSFERED ALL BLOCKS
	TLNE	S,(FL.IO)	;WRITING?
	CAILE	F,LB2HOM+LBOBAT	;YES, ON HOM OR BAT BLOCKS?
	CAIA			;NO
	HALT	.		;YES,  DON'T MAKE THINGS WORSE
	PUSHJ	P,R12CLR	;MAKE SURE THE RH10/RH20 IS CLEARED
	PUSHJ	P,R12SET	;MAKE IOWDS, TELL DRIVE WHERE TO START
IFN FTKL10,<
	JUMPE	W,R10XFR	;DIFFERENT IF RH10
	MOVSI	T1,<(DO.2ST)>(U) ;TALK TO STCR AND SPECIFIED DRIVE
	DPB	T4,[POINT 10,T1,29] ;STORE -VE BLOCKCOUNT
	JRST	R12XF1		;JOIN COMMON CODE
>
R10XFR:	MOVSI	T1,<(DO.1CR)>(U) ;TALK TO COMMAND REGISTER AND SPECIFIED DRIVE
	HRRI	T1,<BOOTWD←6>	;SET INITIAL CONTROL WORD ADDRESS
R12XF1:	TLNN	S,(FL.IO)	;DOING OUTPUT?
	TROA	T1,DO.XRD	;NO, SET READ FUNCTION CODE
	TRO	T1,DO.XWT	;YES, SET WRITE FUNCTION CODE
	XCT	DODATO		;START THE TRANSFER
	PUSHJ	P,R12WAT	;WAIT FOR IT TO COMPLETE
	PUSHJ	P,R12CHK	;CHECK FOR ERRORS
	  POPJ	P,		;GIVE NON-SKIP RETURN IF ERRORS OR TIMED OUT
	JRST	R12XFR		;DO MORE IF ANY BLOCKS LEFT
;ROUTINE TO SETUP THE CHANNEL COMMAND LIST FOR THIS TRANSFER AND ;⊗ R12SET R12SE1 R12SE2 R12SE3 R12SE4 R12SE5 R12SE6
;TELL THE DRIVE WHERE TO START THE TRANSFER.  CALL WITH THE STANDARD
;AC'S SETUP.
;CALL:	PUSHJ	P,R12SET
;RETURN+1 ALWAYS
;RETURNS WITH M, R, AND F UPDATED TO REFLECT THIS TRANSFER AND
;	 T4/NEGATIVE BLOCKCOUNT FOR THIS TRANSFER

R12SET:	MOVEI	T4,0		;INITIALIZE BLOCK COUNT TO 0
IFN FTKL10,<
	JUMPE	W,R12SE2	;NO LOGOUT AREA FOR RH10'S
	HRRZ	T1,DVCTAB(J)	;GET DEVICE CODE FOR THIS DEVICE
	LSH	T1,2		;TIMES 2
	SUBI	T1,540		;COMPUTE OFFSET IN EPT OF LOGOUT AREA
	MOVE	T2,EPTADR	;GET PHYSICAL ADDRESS OF THE EPT
	ADDI	T2,R2IOWD-EPT	;ADD OFFSET TO FIRST IOWD
	TLO	T2,(RH2JMP)	;MAKE IT A JUMP WORD
	MOVEM	T2,EPT(T1)	;STORE JUMP WORD IN LOGOUT AREA
	MOVSI	T1,-<R2IOWL-1>	;MAKE AOBJN POINTER TO IOWD LIST
R12SE1:	JUMPLE	M,R12SE5	;STOP WHEN DONE ENTIRE TRANSFER
>
R12SE2:	MOVEI	T2,(M)		;ASSUME LESS THAN MAX
	CAMLE	M,[R1BCNT
		   R2BCNT](W)	;ARE WE CORRECT?
	MOVE	T2,[R1BCNT
		    R2BCNT](W)	;NO, MAKE IT THE MAX POSSIBLE IN 1 IOWD
	SUBI	M,(T2)		;DECREMENT BLOCKS REMAINING
	SUBI	T4,(T2)		;AND BLOCKS DONE
	LSH	T2,B2WLSH	;CONVERT TO WORDS
IFN FTKL10,<
	JUMPE	W,R12SE3	;GO IF RH10
	LSH	T2,↑D18+4	;POSITION IN IOWD
	TLO	T2,(RH2TRA)	;MAKE THE OPCODE A TRANSFER
	IOR	T2,R		;STORE PHYSICAL ADDRESS
	MOVEM	T2,R2IOWD(T1)	;STORE IN CHANNEL COMMAND LIST
	ADDI	R,R2WCNT	;INCREMENT CORE ADDRESS FOR NEXT TIME
	JRST	R12SE4		;JOIN COMMON CODE
>
R12SE3:	MOVNS	T2		;RH10'S WANT A NEGATIVE WORDCOUNT
	LSH	T2,↑D18		;MOVE TO LH
	XCT	DOCONI		;GET CONI FOR DRIVE
	TLNE	T1,(CI.122)	;SKIP IF 18 BIT DF10
	LSH	T2,4		;DF10C'S ONLY HAVE 14 BITS OF WORDCOUNT
	IOR	T2,R		;STORE PHYSICAL ADDRESS
	SUBI	T2,1		;AND ADDRESS-1
	MOVEM	T2,.VPAG0+BOOTWD ;STORE IOWD IN LOW CORE
	SETZM	.VPAG0+BOOTWD+1 ;INSURE IOWD TERMINATION
	ADDI	R,R1WCNT	;INCREMENT CORE ADDRESS FOR NEXT TIME
IFN FTKL10,<
	JRST	R12SE6		;DO ONLY ONE IOWD FOR AN RH10
R12SE4:	AOBJN	T1,R12SE1	;DO AS MANY AS POSSIBLE
R12SE5:	SETZM	R2IOWD(T1)	;STORE HALT IOWD TO TERMINATE LIST
>
R12SE6:	MOVE	T1,F		;COPY BLOCK ADDRESS
	SUB	F,T4		;UPDATE FOR AMOUNT OF THIS TRANSFER
	IDIV	T1,DRVBPC	;T1=CYLINDER, T2=REMAINDER
	HRLI	T1,<(DO.XDC)>(U) ;STORE IN DESIRED CYLINDER REGISTER
	XCT	DODATO		;TELL THE DRIVE
	IDIV	T2,DRVBPT	;T2=TRACK, T3=SECTOR
	DPB	T2,[POINT 8,T3,27] ;POSITION CORRECTLY
	MOVSI	T1,<(DO.XDS)>(U) ;TALK TO THE BLOCK ADDRESS REGISTER
	HRRI	T1,(T3)		;STORE ADDRESS
	XCT	DODATO		;TELL THE DRIVE
	POPJ	P,		;RETURN
;ROUTINE TO INITIALIZE THE RH10/RH20 FOR A TRANSFER. ;⊗ R12INI R12CHK
;CALL:	PUSHJ	P,R12INI
;RETURN+1 IF INITIALIZATION FAILED
;RETURN+2 IF SUCCESSFUL

R12INI:	XCT	DOCONI		;GET CONI IN T1
	JUMPE	T1,CPOPJ	;NO BITS MEANS IT DOESN'T EXIST
	PUSHJ	P,R12CLR	;BLAST THE RH10/RH20 INTO A KNOWN STATE
	MOVSI	T1,<(DO.XDT)>(U) ;NEED DRIVE TYPE REGISTER FOR THIS DRIVE
	PUSHJ	P,DRVTYP	;READ AND CHECK IT
	  POPJ	P,		;NO MATCH
	MOVSI	T1,<(DO.XCR)>(U) ;POINT TO DRIVE CONTROL REGISTER
	HRRI	T1,DO.XCL	;FUNCTION IS DRIVE CLEAR
	XCT	DODATO		;CLEAR THE DRIVE
	HRRI	T1,DO.XRP	;FOLLOWED BY A READIN
	XCT	DODATO		;  PRESET
	MOVSI	T1,<(DO.XSR)>(U) ;SETUP TO READ STATUS REGISTER
	PUSHJ	P,REDREG	;DO SO
	ANDI	T1,DI.XSM	;MASK, IGNORING WRITE LOCK, PGM
	CAIE	T1,DI.XSB	;IS IT OK?
	POPJ	P,		;NO
	JRST	CPOPJ1		;GIVE SKIP RETURN


;ROUTINE TO CHECK THE RH10/RH20 FOR ERRORS IN THE LAST TRANSFER.
;CALL:	PUSHJ	P,R12CHK
;RETURN+1 IF ERRORS DETECTED
;RETURN+2 IF NO ERRORS

R12CHK:	MOVSI	T1,<(DO.XSR)>(U) ;SET TO READ STATUS REGISTER
	PUSHJ	P,REDREG	;DO SO
	TRNE	T1,DI.XCE	;COMPOSITE ERROR?
	POPJ	P,		;YES, GIVE ERROR RETURN
	MOVE	T1,[CI.1ER
		    CI.2ER](W)	;GET CONI ERROR BITS FOR CONTROLLER
	XCT	DOCNSO		;ANY SET?
	JRST	CPOPJ1		;NO, GIVE SKIP RETURN
	POPJ	P,		;YES
;ROUTINE TO WAIT FOR THE RH10/RH20 TO FINISH A TRANSFER. ;⊗ R12WAT R12CLR
;CALL:	PUSHJ	P,R12WAT
;RETURN+1 IF SUCCESSFUL
;RETURN+2 IF TIMED OUT

R12WAT:	MOVSI	T2,10		;LOOP COUNT = ABOUT 7 SECONDS
	MOVE	T1,[CI.1RA!CI.XDN
		    CI.2RA!CI.XDN](W) ;WAIT FOR DONE OR RAE TO COME UP
	XCT	DOCNSO		;IN THE CONI
	SOJG	T2,.-1		;HASN'T YET, WAIT FOR IT
	JUMPLE	T2,CPOPJ1	;GIVE SKIP RETURN IF TIMED OUT
	POPJ	P,		;RETURN


;ROUTINE TO FORCE THE RH10/RH20 INTO A KNOWN STATE FOR A TRANSFER.
;CALL:	PUSHJ	P,R12CLR
;RETURN+1 ALWAYS

R12CLR:	MOVEI	T1,CO.XMI	;DO A
	XCT	DOCONO		;  MASSBUS INIT
IFN FTKL10,<
	MOVEI	T1,CO.XSX	;THEN A
	XCT	DOCONO		;  STOP TRANSFER
	MOVEI	T1,CO.XDN	;THEN A
	XCT	DOCONO		;  CLEAR DONE
	MOVEI	T1,CO.2ME	;AND FINALLY A
	XCT	DOCONO		;  MASSBUS ENABLE
>
	POPJ	P,


>;END IFN FTKL10!FTKI10
IFN FTKS10,< ;⊗ R11WRT R11RED R11XFR R11XF1
	SUBTTL	RH11 DEVICE DEPENDENT ROUTINES


;ROUTINES TO READ FROM/WRITE TO A DRIVE ON AN RH11.  CALL WITH THE
;STANDARD AC'S SETUP.  TRANSLATES DEVICE INDEPENDENT TRANSFER REQUEST
;TO AS MANY TRANSFERS AS NECESSARY TO MAKE THE RH11 HAPPY.
;CALL:	PUSHJ	P,R11RED -OR- PUSHJ	P,R11WRT
;RETURN+1 IF I/O ERRORS
;RETURN+2 IF TRANSFER WAS SUCCESSFUL

R11WRT:	TLOA	S,(FL.IO)	;SET FLAG FOR OUTPUT
R11RED:	TLZ	S,(FL.IO)	;CLEAR FLAG FOR INPUT
	PUSHJ	P,SAVFR		;SAVE F AND R
	HRLZ	T4,DVCTAB(J)	;SET T4=UBA,,0
	PUSHJ	P,R11INI	;INITIALIZE THE RH11
	  POPJ	P,		;FAILED
R11XFR:	JUMPLE	M,CPOPJ1	;DONE WHEN TRANSFERED ALL BLOCKS
	TLNE	S,(FL.IO)	;WRITING?
	CAILE	F,LB2HOM+LBOBAT ;YES, ON HOM OR BAT BLOCKS?
	CAIA			;NO
	HALT	.		;YES, DON'T MAKE THINGS WORSE
	PUSHJ	P,R11CLR	;CLEAR THE RH11
	WRIO	U,SO.CS2(T4)	;SELECT DRIVE
	PUSH	P,T4		;SAVE T4
	PUSHJ	P,R11SET	;SET UBA MAP SLOTS, DRIVE LBN
	POP	P,T4		;RESTORE T4
	MOVEI	T1,SO.WRT	;ASSUME WRITING
	TLNN	S,(FL.IO)	;ARE WE CORRECT?
	MOVEI	T1,SO.RED	;NO, SET READING
	WRIO	T1,SO.CS1(T4)	;START THE TRANSFER
	MOVSI	T2,2		;LOOP COUNT
R11XF1:	RDIO	T1,SO.CS1(T4)	;READ STATUS REGISTER
	TRNN	T1,SI.RDY	;READY COME UP?
	SOJG	T2,R11XF1	;NO, LOOP
	JUMPLE	T2,CPOPJ	;ERROR RETURN IF TIMED OUT
	TRNE	T1,SI.S1E	;ERRORS?
	POPJ	P,		;YES
	JRST	R11XFR		;DO MORE IF ANY BLOCKS LEFT
;ROUTINE TO SETUP THE UBA MAPPING REGISTERS, AND THE DRIVE REGISTERS ;⊗ R11SET R11SE1
;FOR THIS TRANSFER.  CALL WITH THE STANDARD AC'S SETUP.
;CALL:
;	T4/UBA,,0
;	PUSHJ	P,R11SET
;RETURN+1 ALWAYS
;RETURNS WITH M, R, AND F UPDATED TO REFLECT THIS TRANSFER.
;DESTROYS T4

R11SET:	MOVEI	T1,(R)		;GET ADDRESS OF FIRST WORD TO TRANSFER
	ANDI	T1,PAGSIZ-1	;ISOLATE OFFSET OF FIRST WORD IN PAGE
	LSH	T1,2		;MAKE IT A BYTE OFFSET
	WRIO	T1,SO.BA(T4)	;SET THE BUS ADDRESS REGISTER
	MOVE	T1,F		;COPY LBN OF FIRST BLOCK TO TRANSFER
	IDIV	T1,DRVBPC	;T1=CYLINDER, T2=BLOCK IN CYLINDER
	WRIO	T1,SO.DC(T4)	;SET DESIRED CYLINDER REGISTER
	IDIV	T2,DRVBPT	;T2=TRACK, T3=BLOCK IN TRACK
	DPB	T2,[POINT 8,T3,27] ;POSITION TRACK NUMBER
	WRIO	T3,SO.DA(T4)	;TELL DRIVE
	MOVEI	T1,(M)		;ASSUME WE CAN DO ALL OF TRANSFER
	CAILE	T1,RSBCNT	;LARGER THAN MAX?
	MOVEI	T1,RSBCNT	;YES, USE MAX
	SUBI	M,(T1)		;ADJUST M FOR NEXT TIME
	ADDI	F,(T1)		;ADVANCE TO FIRST BLOCK OF NEXT TRANSFER
	MOVE	T2,R		;COPY CORE ADDRESS OF FIRST WORD
	LSH	T1,B2WLSH	;COMPUTE WORD COUNT
	ADD	R,T1		;ADVANCE CORE ADDRESS FOR NEXT TIME
	LSH	T1,1		;COMPUTE PDP11 WORD COUNT
	MOVNS	T1		;MAKE IT NEGATIVE
	WRIO	T1,SO.WC(T4)	;SET WORD COUNT REGISTER
	LSH	T2,W2PLSH	;COMPUTE PAGE NUMBER OF 1ST PAGE
	MOVE	T1,R		;GET ADDRESS OF FIRST WORD OF NEXT TRANSFER
	SUBI	T1,1		;MAKE IT LAST ADDRESS OF THIS TRANSFER
	LSH	T1,W2PLSH	;COMPUTE PAGE NUMBER
	SUBI	T1,-1(T2)	;COMPUTE NUMBER OF PAGES TO MAP
	MOVNS	T1		;MAKE IT NEGATIVE
	HRL	T2,T1		;AND MAKE AN AOBJN POINTER
	TRO	T2,SO.VFT	;SET VALID AND FAST TRANSFER
R11SE1:	WRIO	T2,SO.UPR(T4)	;MAP ONE PAGE
	ADDI	T4,1		;INCREMENT UBA MAP ADDRESS
	AOBJN	T2,R11SE1	;LOOP FOR ALL
	POPJ	P,		;RETURN
;ROUTINE TO INITIALIZE THE RH11 FOR A TRANSFER. ;⊗ R11INI R11CLR
;CALL:
;	T4/UBA,,0
;	PUSHJ	P,R11INI
;RETURN+1 IF INITIALIZATION FAILED
;RETURN+2 IF SUCCESSFUL

R11INI:	RDIO	T1,SO.USR(T4)	;READ UBA STATUS REGISTER
	TRNE	T1,SI.UER	;ANY ERRORS?
	POPJ	P,		;YES, ERROR
	PUSHJ	P,R11CLR	;CLEAR THE RH11
	WRIO	U,SO.CS2(T4)	;SELECT DRIVE
	RDIO	T1,SI.DT(T4)	;READ DRIVE TYPE REGISTER
	PUSHJ	P,DRVTYP	;CHECK IT
	  POPJ	P,		;FAILED
	MOVEI	T1,SO.DCL	;GET DRIVE CLEAR FUNCTION
	WRIO	T1,SO.CS1(T4)	;DO IT
	MOVEI	T1,SO.RIP	;GET READIN PRESET FUNCTION
	WRIO	T1,SO.CS1(T4)	;DO IT
	RDIO	T1,SO.DS(T4)	;READ DRIVE STATUS REGISTER
	ANDI	T1,SO.DSM	;MASK, IGNORING WRITE LOCK, PGM
	CAIE	T1,SO.DSB	;IS IT OK?
	POPJ	P,		;NO
	JRST	CPOPJ1		;GIVE SKIP RETURN


;ROUTINE TO FORCE THE RH11 INTO A KNOWN STATE.
;CALL:
;	T4/UBA,,0
;	PUSHJ	P,R11CLR
;RETURN+1 ALWAYS

R11CLR:	MOVEI	T1,SO.UBI	;UBA INIT
	WRIO	T1,SO.USR(T4)	;CLEAR THE UBA/DRIVES
	POPJ	P,		;RETURN


>;END IFN FTKS10
	$DEPHASE ;⊗ BOOLEN BOOPGS BOOEND

	BOOLEN==.-BOOTVA	;LENGTH OF BOOT
	BOOPGS==<BOOLEN+PAGSIZ-1>/PAGSIZ ;LENGTH IN PAGES


	DEFINE	PRTLEN(FPAGE,LPAGE),<
PRINTX [BOOT will be loaded into physical pages FPAGE through LPAGE]
>

IF2 <
IFG <FTPAGE+BOOPGS-1000>,<
PRINTX ?BOOT assembly crosses above 256K boundary
>
IFLE <FTPAGE+BOOPGS-1000>,<
PRTLEN (\FTPAGE,\<FTPAGE+BOOPGS-1>)
>>


BOOEND:	END	BOOT